Version 0.5.0 of tinydtls

Dependents:   tinydtls_test_cellular tinydtls_test_ethernet tiny-dtls

Committer:
ashleymills
Date:
Wed Feb 12 09:30:16 2014 +0000
Revision:
1:598a56fe116e
Parent:
0:ff9ebe0cf0e9
Explicitly removed something instead of relying on MACRO to disable it. Mbed can't use it.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ashleymills 0:ff9ebe0cf0e9 1 /* dtls -- a very basic DTLS implementation
ashleymills 0:ff9ebe0cf0e9 2 *
ashleymills 0:ff9ebe0cf0e9 3 * Copyright (C) 2011--2012 Olaf Bergmann <bergmann@tzi.org>
ashleymills 0:ff9ebe0cf0e9 4 * Copyright (C) 2013 Hauke Mehrtens <hauke@hauke-m.de>
ashleymills 0:ff9ebe0cf0e9 5 *
ashleymills 0:ff9ebe0cf0e9 6 * Permission is hereby granted, free of charge, to any person
ashleymills 0:ff9ebe0cf0e9 7 * obtaining a copy of this software and associated documentation
ashleymills 0:ff9ebe0cf0e9 8 * files (the "Software"), to deal in the Software without
ashleymills 0:ff9ebe0cf0e9 9 * restriction, including without limitation the rights to use, copy,
ashleymills 0:ff9ebe0cf0e9 10 * modify, merge, publish, distribute, sublicense, and/or sell copies
ashleymills 0:ff9ebe0cf0e9 11 * of the Software, and to permit persons to whom the Software is
ashleymills 0:ff9ebe0cf0e9 12 * furnished to do so, subject to the following conditions:
ashleymills 0:ff9ebe0cf0e9 13 *
ashleymills 0:ff9ebe0cf0e9 14 * The above copyright notice and this permission notice shall be
ashleymills 0:ff9ebe0cf0e9 15 * included in all copies or substantial portions of the Software.
ashleymills 0:ff9ebe0cf0e9 16 *
ashleymills 0:ff9ebe0cf0e9 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
ashleymills 0:ff9ebe0cf0e9 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
ashleymills 0:ff9ebe0cf0e9 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
ashleymills 0:ff9ebe0cf0e9 20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
ashleymills 0:ff9ebe0cf0e9 21 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ashleymills 0:ff9ebe0cf0e9 22 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
ashleymills 0:ff9ebe0cf0e9 23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
ashleymills 0:ff9ebe0cf0e9 24 * SOFTWARE.
ashleymills 0:ff9ebe0cf0e9 25 */
ashleymills 0:ff9ebe0cf0e9 26
ashleymills 0:ff9ebe0cf0e9 27 #include "config.h"
ashleymills 0:ff9ebe0cf0e9 28 #include "dtls_time.h"
ashleymills 0:ff9ebe0cf0e9 29
ashleymills 0:ff9ebe0cf0e9 30 #define __DEBUG__ 0
ashleymills 0:ff9ebe0cf0e9 31 #ifndef __MODULE__
ashleymills 0:ff9ebe0cf0e9 32 #define __MODULE__ "dtls.c"
ashleymills 0:ff9ebe0cf0e9 33 #endif
ashleymills 0:ff9ebe0cf0e9 34
ashleymills 0:ff9ebe0cf0e9 35 #include "dbg.h"
ashleymills 0:ff9ebe0cf0e9 36
ashleymills 0:ff9ebe0cf0e9 37 #include <stdio.h>
ashleymills 0:ff9ebe0cf0e9 38 #include <stdlib.h>
ashleymills 0:ff9ebe0cf0e9 39 #ifdef HAVE_ASSERT_H
ashleymills 0:ff9ebe0cf0e9 40 #include <assert.h>
ashleymills 0:ff9ebe0cf0e9 41 #endif
ashleymills 0:ff9ebe0cf0e9 42 #ifndef WITH_CONTIKI
ashleymills 0:ff9ebe0cf0e9 43 #include <stdlib.h>
ashleymills 0:ff9ebe0cf0e9 44 #include "uthash.h"
ashleymills 0:ff9ebe0cf0e9 45 #else /* WITH_CONTIKI */
ashleymills 0:ff9ebe0cf0e9 46 # ifndef NDEBUG
ashleymills 0:ff9ebe0cf0e9 47 # define DEBUG DEBUG_PRINT
ashleymills 0:ff9ebe0cf0e9 48 # include "net/uip-debug.h"
ashleymills 0:ff9ebe0cf0e9 49 # endif /* NDEBUG */
ashleymills 0:ff9ebe0cf0e9 50 #endif /* WITH_CONTIKI */
ashleymills 0:ff9ebe0cf0e9 51
ashleymills 0:ff9ebe0cf0e9 52 #include "debug.h"
ashleymills 0:ff9ebe0cf0e9 53 #include "numeric.h"
ashleymills 0:ff9ebe0cf0e9 54 #include "netq.h"
ashleymills 0:ff9ebe0cf0e9 55 #include "dtls.h"
ashleymills 0:ff9ebe0cf0e9 56
ashleymills 0:ff9ebe0cf0e9 57 #ifdef WITH_SHA256
ashleymills 0:ff9ebe0cf0e9 58 # include "sha2/sha2.h"
ashleymills 0:ff9ebe0cf0e9 59 #endif
ashleymills 0:ff9ebe0cf0e9 60
ashleymills 0:ff9ebe0cf0e9 61 #define dtls_set_version(H,V) dtls_int_to_uint16(&(H)->version, (V))
ashleymills 0:ff9ebe0cf0e9 62 #define dtls_set_content_type(H,V) ((H)->content_type = (V) & 0xff)
ashleymills 0:ff9ebe0cf0e9 63 #define dtls_set_length(H,V) ((H)->length = (V))
ashleymills 0:ff9ebe0cf0e9 64
ashleymills 0:ff9ebe0cf0e9 65 #define dtls_get_content_type(H) ((H)->content_type & 0xff)
ashleymills 0:ff9ebe0cf0e9 66 #define dtls_get_version(H) dtls_uint16_to_int(&(H)->version)
ashleymills 0:ff9ebe0cf0e9 67 #define dtls_get_epoch(H) dtls_uint16_to_int(&(H)->epoch)
ashleymills 0:ff9ebe0cf0e9 68 #define dtls_get_sequence_number(H) dtls_uint48_to_ulong(&(H)->sequence_number)
ashleymills 0:ff9ebe0cf0e9 69 #define dtls_get_fragment_length(H) dtls_uint24_to_int(&(H)->fragment_length)
ashleymills 0:ff9ebe0cf0e9 70
ashleymills 0:ff9ebe0cf0e9 71 #ifndef WITH_CONTIKI
ashleymills 0:ff9ebe0cf0e9 72 #define HASH_FIND_PEER(head,sess,out) \
ashleymills 0:ff9ebe0cf0e9 73 HASH_FIND(hh,head,sess,sizeof(session_t),out)
ashleymills 0:ff9ebe0cf0e9 74 #define HASH_ADD_PEER(head,sess,add) \
ashleymills 0:ff9ebe0cf0e9 75 HASH_ADD(hh,head,sess,sizeof(session_t),add)
ashleymills 0:ff9ebe0cf0e9 76 #define HASH_DEL_PEER(head,delptr) \
ashleymills 0:ff9ebe0cf0e9 77 HASH_DELETE(hh,head,delptr)
ashleymills 0:ff9ebe0cf0e9 78 #endif /* WITH_CONTIKI */
ashleymills 0:ff9ebe0cf0e9 79
ashleymills 0:ff9ebe0cf0e9 80 #define DTLS_RH_LENGTH sizeof(dtls_record_header_t)
ashleymills 0:ff9ebe0cf0e9 81 #define DTLS_HS_LENGTH sizeof(dtls_handshake_header_t)
ashleymills 0:ff9ebe0cf0e9 82 #define DTLS_CH_LENGTH sizeof(dtls_client_hello_t) /* no variable length fields! */
ashleymills 0:ff9ebe0cf0e9 83 #define DTLS_COOKIE_LENGTH_MAX 32
ashleymills 0:ff9ebe0cf0e9 84 #define DTLS_CH_LENGTH_MAX sizeof(dtls_client_hello_t) + DTLS_COOKIE_LENGTH_MAX + 12 + 26
ashleymills 0:ff9ebe0cf0e9 85 #define DTLS_HV_LENGTH sizeof(dtls_hello_verify_t)
ashleymills 0:ff9ebe0cf0e9 86 #define DTLS_SH_LENGTH (2 + DTLS_RANDOM_LENGTH + 1 + 2 + 1)
ashleymills 0:ff9ebe0cf0e9 87 #define DTLS_CE_LENGTH (3 + 3 + 27 + DTLS_EC_KEY_SIZE + DTLS_EC_KEY_SIZE)
ashleymills 0:ff9ebe0cf0e9 88 #define DTLS_SKEXEC_LENGTH (1 + 2 + 1 + 1 + DTLS_EC_KEY_SIZE + DTLS_EC_KEY_SIZE + 2 + 70)
ashleymills 0:ff9ebe0cf0e9 89 #define DTLS_SKEXECPSK_LENGTH_MIN 2
ashleymills 0:ff9ebe0cf0e9 90 #define DTLS_SKEXECPSK_LENGTH_MAX 2 + DTLS_PSK_MAX_CLIENT_IDENTITY_LEN
ashleymills 0:ff9ebe0cf0e9 91 #define DTLS_CKXPSK_LENGTH_MIN 2
ashleymills 0:ff9ebe0cf0e9 92 #define DTLS_CKXEC_LENGTH (1 + 1 + DTLS_EC_KEY_SIZE + DTLS_EC_KEY_SIZE)
ashleymills 0:ff9ebe0cf0e9 93 #define DTLS_CV_LENGTH (1 + 1 + 2 + 1 + 1 + 1 + 1 + DTLS_EC_KEY_SIZE + 1 + 1 + DTLS_EC_KEY_SIZE)
ashleymills 0:ff9ebe0cf0e9 94 #define DTLS_FIN_LENGTH 12
ashleymills 0:ff9ebe0cf0e9 95
ashleymills 0:ff9ebe0cf0e9 96 #define HS_HDR_LENGTH DTLS_RH_LENGTH + DTLS_HS_LENGTH
ashleymills 0:ff9ebe0cf0e9 97 #define HV_HDR_LENGTH HS_HDR_LENGTH + DTLS_HV_LENGTH
ashleymills 0:ff9ebe0cf0e9 98
ashleymills 0:ff9ebe0cf0e9 99 #define HIGH(V) (((V) >> 8) & 0xff)
ashleymills 0:ff9ebe0cf0e9 100 #define LOW(V) ((V) & 0xff)
ashleymills 0:ff9ebe0cf0e9 101
ashleymills 0:ff9ebe0cf0e9 102 #define DTLS_RECORD_HEADER(M) ((dtls_record_header_t *)(M))
ashleymills 0:ff9ebe0cf0e9 103 #define DTLS_HANDSHAKE_HEADER(M) ((dtls_handshake_header_t *)(M))
ashleymills 0:ff9ebe0cf0e9 104
ashleymills 0:ff9ebe0cf0e9 105 #define HANDSHAKE(M) ((dtls_handshake_header_t *)((M) + DTLS_RH_LENGTH))
ashleymills 0:ff9ebe0cf0e9 106 #define CLIENTHELLO(M) ((dtls_client_hello_t *)((M) + HS_HDR_LENGTH))
ashleymills 0:ff9ebe0cf0e9 107
ashleymills 0:ff9ebe0cf0e9 108 /* The length check here should work because dtls_*_to_int() works on
ashleymills 0:ff9ebe0cf0e9 109 * unsigned char. Otherwise, broken messages could cause severe
ashleymills 0:ff9ebe0cf0e9 110 * trouble. Note that this macro jumps out of the current program flow
ashleymills 0:ff9ebe0cf0e9 111 * when the message is too short. Beware!
ashleymills 0:ff9ebe0cf0e9 112 */
ashleymills 0:ff9ebe0cf0e9 113 #define SKIP_VAR_FIELD(P,L,T) { \
ashleymills 0:ff9ebe0cf0e9 114 if (L < dtls_ ## T ## _to_int(P) + sizeof(T)) \
ashleymills 0:ff9ebe0cf0e9 115 goto error; \
ashleymills 0:ff9ebe0cf0e9 116 L -= dtls_ ## T ## _to_int(P) + sizeof(T); \
ashleymills 0:ff9ebe0cf0e9 117 P += dtls_ ## T ## _to_int(P) + sizeof(T); \
ashleymills 0:ff9ebe0cf0e9 118 }
ashleymills 0:ff9ebe0cf0e9 119
ashleymills 0:ff9ebe0cf0e9 120 /* some constants for the PRF */
ashleymills 0:ff9ebe0cf0e9 121 #define PRF_LABEL(Label) prf_label_##Label
ashleymills 0:ff9ebe0cf0e9 122 #define PRF_LABEL_SIZE(Label) (sizeof(PRF_LABEL(Label)) - 1)
ashleymills 0:ff9ebe0cf0e9 123
ashleymills 0:ff9ebe0cf0e9 124 static const unsigned char prf_label_master[] = "master secret";
ashleymills 0:ff9ebe0cf0e9 125 static const unsigned char prf_label_key[] = "key expansion";
ashleymills 0:ff9ebe0cf0e9 126 static const unsigned char prf_label_client[] = "client";
ashleymills 0:ff9ebe0cf0e9 127 static const unsigned char prf_label_server[] = "server";
ashleymills 0:ff9ebe0cf0e9 128 static const unsigned char prf_label_finished[] = " finished";
ashleymills 0:ff9ebe0cf0e9 129
ashleymills 0:ff9ebe0cf0e9 130 /* first part of Raw public key, the is the start of the Subject Public Key */
ashleymills 0:ff9ebe0cf0e9 131 static const unsigned char cert_asn1_header[] = {
ashleymills 0:ff9ebe0cf0e9 132 0x30, 0x59, /* SEQUENCE, length 89 bytes */
ashleymills 0:ff9ebe0cf0e9 133 0x30, 0x13, /* SEQUENCE, length 19 bytes */
ashleymills 0:ff9ebe0cf0e9 134 0x06, 0x07, /* OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1) */
ashleymills 0:ff9ebe0cf0e9 135 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01,
ashleymills 0:ff9ebe0cf0e9 136 0x06, 0x08, /* OBJECT IDENTIFIER prime256v1 (1 2 840 10045 3 1 7) */
ashleymills 0:ff9ebe0cf0e9 137 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07,
ashleymills 0:ff9ebe0cf0e9 138 0x03, 0x42, 0x00, /* BIT STRING, length 66 bytes, 0 bits unused */
ashleymills 0:ff9ebe0cf0e9 139 0x04 /* uncompressed, followed by the r und s values of the public key */
ashleymills 0:ff9ebe0cf0e9 140 };
ashleymills 0:ff9ebe0cf0e9 141
ashleymills 0:ff9ebe0cf0e9 142 static dtls_context_t the_dtls_context;
ashleymills 0:ff9ebe0cf0e9 143
ashleymills 0:ff9ebe0cf0e9 144 #ifdef WITH_CONTIKI
ashleymills 0:ff9ebe0cf0e9 145 PROCESS(dtls_retransmit_process, "DTLS retransmit process");
ashleymills 0:ff9ebe0cf0e9 146 #endif
ashleymills 0:ff9ebe0cf0e9 147
ashleymills 0:ff9ebe0cf0e9 148 void
ashleymills 0:ff9ebe0cf0e9 149 dtls_init() {
ashleymills 0:ff9ebe0cf0e9 150 dtls_clock_init();
ashleymills 0:ff9ebe0cf0e9 151 netq_init();
ashleymills 0:ff9ebe0cf0e9 152 crypto_init();
ashleymills 0:ff9ebe0cf0e9 153 peer_init();
ashleymills 0:ff9ebe0cf0e9 154 }
ashleymills 0:ff9ebe0cf0e9 155
ashleymills 0:ff9ebe0cf0e9 156 /* Calls cb_alert() with given arguments if defined, otherwise an
ashleymills 0:ff9ebe0cf0e9 157 * error message is logged and the result is -1. This is just an
ashleymills 0:ff9ebe0cf0e9 158 * internal helper.
ashleymills 0:ff9ebe0cf0e9 159 */
ashleymills 0:ff9ebe0cf0e9 160 #define CALL(Context, which, ...) \
ashleymills 0:ff9ebe0cf0e9 161 ((Context)->h && (Context)->h->which \
ashleymills 0:ff9ebe0cf0e9 162 ? (Context)->h->which((Context), ##__VA_ARGS__) \
ashleymills 0:ff9ebe0cf0e9 163 : -1)
ashleymills 0:ff9ebe0cf0e9 164
ashleymills 0:ff9ebe0cf0e9 165 /**
ashleymills 0:ff9ebe0cf0e9 166 * Sends the fragment of length \p buflen given in \p buf to the
ashleymills 0:ff9ebe0cf0e9 167 * specified \p peer. The data will be MAC-protected and encrypted
ashleymills 0:ff9ebe0cf0e9 168 * according to the selected cipher and split into one or more DTLS
ashleymills 0:ff9ebe0cf0e9 169 * records of the specified \p type. This function returns the number
ashleymills 0:ff9ebe0cf0e9 170 * of bytes that were sent, or \c -1 if an error occurred.
ashleymills 0:ff9ebe0cf0e9 171 *
ashleymills 0:ff9ebe0cf0e9 172 * \param ctx The DTLS context to use.
ashleymills 0:ff9ebe0cf0e9 173 * \param peer The remote peer.
ashleymills 0:ff9ebe0cf0e9 174 * \param type The content type of the record.
ashleymills 0:ff9ebe0cf0e9 175 * \param buf The data to send.
ashleymills 0:ff9ebe0cf0e9 176 * \param buflen The actual length of \p buf.
ashleymills 0:ff9ebe0cf0e9 177 * \return Less than zero on error, the number of bytes written otherwise.
ashleymills 0:ff9ebe0cf0e9 178 */
ashleymills 0:ff9ebe0cf0e9 179 static int dtls_send(dtls_context_t *ctx, dtls_peer_t *peer, unsigned char type,
ashleymills 0:ff9ebe0cf0e9 180 uint8 *buf, size_t buflen);
ashleymills 0:ff9ebe0cf0e9 181
ashleymills 0:ff9ebe0cf0e9 182 /**
ashleymills 0:ff9ebe0cf0e9 183 * Stops ongoing retransmissions of handshake messages for @p peer.
ashleymills 0:ff9ebe0cf0e9 184 */
ashleymills 0:ff9ebe0cf0e9 185 static void dtls_stop_retransmission(dtls_context_t *context, dtls_peer_t *peer);
ashleymills 0:ff9ebe0cf0e9 186
ashleymills 0:ff9ebe0cf0e9 187 dtls_peer_t *
ashleymills 0:ff9ebe0cf0e9 188 dtls_get_peer(const dtls_context_t *ctx, const session_t *session) {
ashleymills 0:ff9ebe0cf0e9 189 dtls_peer_t *p = NULL;
ashleymills 0:ff9ebe0cf0e9 190
ashleymills 0:ff9ebe0cf0e9 191 #ifndef WITH_CONTIKI
ashleymills 0:ff9ebe0cf0e9 192 HASH_FIND_PEER(ctx->peers, session, p);
ashleymills 0:ff9ebe0cf0e9 193 #else /* WITH_CONTIKI */
ashleymills 0:ff9ebe0cf0e9 194 for (p = list_head(ctx->peers); p; p = list_item_next(p))
ashleymills 0:ff9ebe0cf0e9 195 if (dtls_session_equals(&p->session, session))
ashleymills 0:ff9ebe0cf0e9 196 return p;
ashleymills 0:ff9ebe0cf0e9 197 #endif /* WITH_CONTIKI */
ashleymills 0:ff9ebe0cf0e9 198
ashleymills 0:ff9ebe0cf0e9 199 return p;
ashleymills 0:ff9ebe0cf0e9 200 }
ashleymills 0:ff9ebe0cf0e9 201
ashleymills 0:ff9ebe0cf0e9 202 static void
ashleymills 0:ff9ebe0cf0e9 203 dtls_add_peer(dtls_context_t *ctx, dtls_peer_t *peer) {
ashleymills 0:ff9ebe0cf0e9 204 #ifndef WITH_CONTIKI
ashleymills 0:ff9ebe0cf0e9 205 HASH_ADD_PEER(ctx->peers, session, peer);
ashleymills 0:ff9ebe0cf0e9 206 #else /* WITH_CONTIKI */
ashleymills 0:ff9ebe0cf0e9 207 list_add(ctx->peers, peer);
ashleymills 0:ff9ebe0cf0e9 208 #endif /* WITH_CONTIKI */
ashleymills 0:ff9ebe0cf0e9 209 }
ashleymills 0:ff9ebe0cf0e9 210
ashleymills 0:ff9ebe0cf0e9 211 int
ashleymills 0:ff9ebe0cf0e9 212 dtls_write(struct dtls_context_t *ctx,
ashleymills 0:ff9ebe0cf0e9 213 session_t *dst, uint8 *buf, size_t len) {
ashleymills 0:ff9ebe0cf0e9 214
ashleymills 0:ff9ebe0cf0e9 215 dtls_peer_t *peer = dtls_get_peer(ctx, dst);
ashleymills 0:ff9ebe0cf0e9 216
ashleymills 0:ff9ebe0cf0e9 217 /* Check if peer connection already exists */
ashleymills 0:ff9ebe0cf0e9 218 if (!peer) { /* no ==> create one */
ashleymills 0:ff9ebe0cf0e9 219 int res;
ashleymills 0:ff9ebe0cf0e9 220
ashleymills 0:ff9ebe0cf0e9 221 /* dtls_connect() returns a value greater than zero if a new
ashleymills 0:ff9ebe0cf0e9 222 * connection attempt is made, 0 for session reuse. */
ashleymills 0:ff9ebe0cf0e9 223 res = dtls_connect(ctx, dst);
ashleymills 0:ff9ebe0cf0e9 224
ashleymills 0:ff9ebe0cf0e9 225 return (res >= 0) ? 0 : res;
ashleymills 0:ff9ebe0cf0e9 226 } else { /* a session exists, check if it is in state connected */
ashleymills 0:ff9ebe0cf0e9 227
ashleymills 0:ff9ebe0cf0e9 228 if (peer->state != DTLS_STATE_CONNECTED) {
ashleymills 0:ff9ebe0cf0e9 229 return 0;
ashleymills 0:ff9ebe0cf0e9 230 } else {
ashleymills 0:ff9ebe0cf0e9 231 return dtls_send(ctx, peer, DTLS_CT_APPLICATION_DATA, buf, len);
ashleymills 0:ff9ebe0cf0e9 232 }
ashleymills 0:ff9ebe0cf0e9 233 }
ashleymills 0:ff9ebe0cf0e9 234 }
ashleymills 0:ff9ebe0cf0e9 235
ashleymills 0:ff9ebe0cf0e9 236 static int
ashleymills 0:ff9ebe0cf0e9 237 dtls_get_cookie(uint8 *msg, int msglen, uint8 **cookie) {
ashleymills 0:ff9ebe0cf0e9 238 /* To access the cookie, we have to determine the session id's
ashleymills 0:ff9ebe0cf0e9 239 * length and skip the whole thing. */
ashleymills 0:ff9ebe0cf0e9 240 if (msglen < DTLS_HS_LENGTH + DTLS_CH_LENGTH + sizeof(uint8))
ashleymills 0:ff9ebe0cf0e9 241 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 242
ashleymills 0:ff9ebe0cf0e9 243 if (dtls_uint16_to_int(msg + DTLS_HS_LENGTH) != DTLS_VERSION)
ashleymills 0:ff9ebe0cf0e9 244 return dtls_alert_fatal_create(DTLS_ALERT_PROTOCOL_VERSION);
ashleymills 0:ff9ebe0cf0e9 245
ashleymills 0:ff9ebe0cf0e9 246 msglen -= DTLS_HS_LENGTH + DTLS_CH_LENGTH;
ashleymills 0:ff9ebe0cf0e9 247 msg += DTLS_HS_LENGTH + DTLS_CH_LENGTH;
ashleymills 0:ff9ebe0cf0e9 248
ashleymills 0:ff9ebe0cf0e9 249 SKIP_VAR_FIELD(msg, msglen, uint8); /* skip session id */
ashleymills 0:ff9ebe0cf0e9 250
ashleymills 0:ff9ebe0cf0e9 251 if (msglen < (*msg & 0xff) + sizeof(uint8))
ashleymills 0:ff9ebe0cf0e9 252 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 253
ashleymills 0:ff9ebe0cf0e9 254 *cookie = msg + sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 255 return dtls_uint8_to_int(msg);
ashleymills 0:ff9ebe0cf0e9 256
ashleymills 0:ff9ebe0cf0e9 257 error:
ashleymills 0:ff9ebe0cf0e9 258 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 259 }
ashleymills 0:ff9ebe0cf0e9 260
ashleymills 0:ff9ebe0cf0e9 261 static int
ashleymills 0:ff9ebe0cf0e9 262 dtls_create_cookie(dtls_context_t *ctx,
ashleymills 0:ff9ebe0cf0e9 263 session_t *session,
ashleymills 0:ff9ebe0cf0e9 264 uint8 *msg, int msglen,
ashleymills 0:ff9ebe0cf0e9 265 uint8 *cookie, int *clen) {
ashleymills 0:ff9ebe0cf0e9 266 unsigned char buf[DTLS_HMAC_MAX];
ashleymills 0:ff9ebe0cf0e9 267 size_t len, e;
ashleymills 0:ff9ebe0cf0e9 268
ashleymills 0:ff9ebe0cf0e9 269 /* create cookie with HMAC-SHA256 over:
ashleymills 0:ff9ebe0cf0e9 270 * - SECRET
ashleymills 0:ff9ebe0cf0e9 271 * - session parameters (only IP address?)
ashleymills 0:ff9ebe0cf0e9 272 * - client version
ashleymills 0:ff9ebe0cf0e9 273 * - random gmt and bytes
ashleymills 0:ff9ebe0cf0e9 274 * - session id
ashleymills 0:ff9ebe0cf0e9 275 * - cipher_suites
ashleymills 0:ff9ebe0cf0e9 276 * - compression method
ashleymills 0:ff9ebe0cf0e9 277 */
ashleymills 0:ff9ebe0cf0e9 278
ashleymills 0:ff9ebe0cf0e9 279 /* We use our own buffer as hmac_context instead of a dynamic buffer
ashleymills 0:ff9ebe0cf0e9 280 * created by dtls_hmac_new() to separate storage space for cookie
ashleymills 0:ff9ebe0cf0e9 281 * creation from storage that is used in real sessions. Note that
ashleymills 0:ff9ebe0cf0e9 282 * the buffer size must fit with the default hash algorithm (see
ashleymills 0:ff9ebe0cf0e9 283 * implementation of dtls_hmac_context_new()). */
ashleymills 0:ff9ebe0cf0e9 284
ashleymills 0:ff9ebe0cf0e9 285 dtls_hmac_context_t hmac_context;
ashleymills 0:ff9ebe0cf0e9 286 dtls_hmac_init(&hmac_context, ctx->cookie_secret, DTLS_COOKIE_SECRET_LENGTH);
ashleymills 0:ff9ebe0cf0e9 287
ashleymills 0:ff9ebe0cf0e9 288 dtls_hmac_update(&hmac_context,
ashleymills 0:ff9ebe0cf0e9 289 (unsigned char *)&session->addr, session->size);
ashleymills 0:ff9ebe0cf0e9 290
ashleymills 0:ff9ebe0cf0e9 291 /* feed in the beginning of the Client Hello up to and including the
ashleymills 0:ff9ebe0cf0e9 292 session id */
ashleymills 0:ff9ebe0cf0e9 293 e = sizeof(dtls_client_hello_t);
ashleymills 0:ff9ebe0cf0e9 294 e += (*(msg + DTLS_HS_LENGTH + e) & 0xff) + sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 295 if (e + DTLS_HS_LENGTH > msglen)
ashleymills 0:ff9ebe0cf0e9 296 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 297
ashleymills 0:ff9ebe0cf0e9 298 dtls_hmac_update(&hmac_context, msg + DTLS_HS_LENGTH, e);
ashleymills 0:ff9ebe0cf0e9 299
ashleymills 0:ff9ebe0cf0e9 300 /* skip cookie bytes and length byte */
ashleymills 0:ff9ebe0cf0e9 301 e += *(uint8 *)(msg + DTLS_HS_LENGTH + e) & 0xff;
ashleymills 0:ff9ebe0cf0e9 302 e += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 303 if (e + DTLS_HS_LENGTH > msglen)
ashleymills 0:ff9ebe0cf0e9 304 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 305
ashleymills 0:ff9ebe0cf0e9 306 dtls_hmac_update(&hmac_context,
ashleymills 0:ff9ebe0cf0e9 307 msg + DTLS_HS_LENGTH + e,
ashleymills 0:ff9ebe0cf0e9 308 dtls_get_fragment_length(DTLS_HANDSHAKE_HEADER(msg)) - e);
ashleymills 0:ff9ebe0cf0e9 309
ashleymills 0:ff9ebe0cf0e9 310 len = dtls_hmac_finalize(&hmac_context, buf);
ashleymills 0:ff9ebe0cf0e9 311
ashleymills 0:ff9ebe0cf0e9 312 if (len < *clen) {
ashleymills 0:ff9ebe0cf0e9 313 memset(cookie + len, 0, *clen - len);
ashleymills 0:ff9ebe0cf0e9 314 *clen = len;
ashleymills 0:ff9ebe0cf0e9 315 }
ashleymills 0:ff9ebe0cf0e9 316
ashleymills 0:ff9ebe0cf0e9 317 memcpy(cookie, buf, *clen);
ashleymills 0:ff9ebe0cf0e9 318 return 0;
ashleymills 0:ff9ebe0cf0e9 319 }
ashleymills 0:ff9ebe0cf0e9 320
ashleymills 0:ff9ebe0cf0e9 321 #ifdef DTLS_CHECK_CONTENTTYPE
ashleymills 0:ff9ebe0cf0e9 322 /* used to check if a received datagram contains a DTLS message */
ashleymills 0:ff9ebe0cf0e9 323 static char const content_types[] = {
ashleymills 0:ff9ebe0cf0e9 324 DTLS_CT_CHANGE_CIPHER_SPEC,
ashleymills 0:ff9ebe0cf0e9 325 DTLS_CT_ALERT,
ashleymills 0:ff9ebe0cf0e9 326 DTLS_CT_HANDSHAKE,
ashleymills 0:ff9ebe0cf0e9 327 DTLS_CT_APPLICATION_DATA,
ashleymills 0:ff9ebe0cf0e9 328 0 /* end marker */
ashleymills 0:ff9ebe0cf0e9 329 };
ashleymills 0:ff9ebe0cf0e9 330 #endif
ashleymills 0:ff9ebe0cf0e9 331
ashleymills 0:ff9ebe0cf0e9 332 /**
ashleymills 0:ff9ebe0cf0e9 333 * Checks if \p msg points to a valid DTLS record. If
ashleymills 0:ff9ebe0cf0e9 334 *
ashleymills 0:ff9ebe0cf0e9 335 */
ashleymills 0:ff9ebe0cf0e9 336 static unsigned int
ashleymills 0:ff9ebe0cf0e9 337 is_record(uint8 *msg, int msglen) {
ashleymills 0:ff9ebe0cf0e9 338 DBG("is_record");
ashleymills 0:ff9ebe0cf0e9 339 unsigned int rlen = 0;
ashleymills 0:ff9ebe0cf0e9 340
ashleymills 0:ff9ebe0cf0e9 341 if (msglen >= DTLS_RH_LENGTH /* FIXME allow empty records? */
ashleymills 0:ff9ebe0cf0e9 342 #ifdef DTLS_CHECK_CONTENTTYPE
ashleymills 0:ff9ebe0cf0e9 343 && strchr(content_types, msg[0])
ashleymills 0:ff9ebe0cf0e9 344 #endif
ashleymills 0:ff9ebe0cf0e9 345 && msg[1] == HIGH(DTLS_VERSION)
ashleymills 0:ff9ebe0cf0e9 346 && msg[2] == LOW(DTLS_VERSION))
ashleymills 0:ff9ebe0cf0e9 347 {
ashleymills 0:ff9ebe0cf0e9 348 rlen = DTLS_RH_LENGTH +
ashleymills 0:ff9ebe0cf0e9 349 dtls_uint16_to_int(DTLS_RECORD_HEADER(msg)->length);
ashleymills 0:ff9ebe0cf0e9 350
ashleymills 0:ff9ebe0cf0e9 351 /* we do not accept wrong length field in record header */
ashleymills 0:ff9ebe0cf0e9 352 if (rlen > msglen)
ashleymills 0:ff9ebe0cf0e9 353 rlen = 0;
ashleymills 0:ff9ebe0cf0e9 354 }
ashleymills 0:ff9ebe0cf0e9 355 return rlen;
ashleymills 0:ff9ebe0cf0e9 356 }
ashleymills 0:ff9ebe0cf0e9 357
ashleymills 0:ff9ebe0cf0e9 358 /**
ashleymills 0:ff9ebe0cf0e9 359 * Initializes \p buf as record header. The caller must ensure that \p
ashleymills 0:ff9ebe0cf0e9 360 * buf is capable of holding at least \c sizeof(dtls_record_header_t)
ashleymills 0:ff9ebe0cf0e9 361 * bytes. Increments sequence number counter of \p peer.
ashleymills 0:ff9ebe0cf0e9 362 * \return pointer to the next byte after the written header
ashleymills 0:ff9ebe0cf0e9 363 */
ashleymills 0:ff9ebe0cf0e9 364 static inline uint8 *
ashleymills 0:ff9ebe0cf0e9 365 dtls_set_record_header(uint8 type, dtls_peer_t *peer, uint8 *buf) {
ashleymills 0:ff9ebe0cf0e9 366
ashleymills 0:ff9ebe0cf0e9 367 dtls_int_to_uint8(buf, type);
ashleymills 0:ff9ebe0cf0e9 368 buf += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 369
ashleymills 0:ff9ebe0cf0e9 370 dtls_int_to_uint16(buf, DTLS_VERSION);
ashleymills 0:ff9ebe0cf0e9 371 buf += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 372
ashleymills 0:ff9ebe0cf0e9 373 if (peer) {
ashleymills 0:ff9ebe0cf0e9 374 memcpy(buf, &peer->epoch, sizeof(uint16) + sizeof(uint48));
ashleymills 0:ff9ebe0cf0e9 375
ashleymills 0:ff9ebe0cf0e9 376 /* increment record sequence counter by 1 */
ashleymills 0:ff9ebe0cf0e9 377 inc_uint(uint48, peer->rseq);
ashleymills 0:ff9ebe0cf0e9 378 } else {
ashleymills 0:ff9ebe0cf0e9 379 memset(buf, 0, sizeof(uint16) + sizeof(uint48));
ashleymills 0:ff9ebe0cf0e9 380 }
ashleymills 0:ff9ebe0cf0e9 381
ashleymills 0:ff9ebe0cf0e9 382 buf += sizeof(uint16) + sizeof(uint48);
ashleymills 0:ff9ebe0cf0e9 383
ashleymills 0:ff9ebe0cf0e9 384 memset(buf, 0, sizeof(uint16));
ashleymills 0:ff9ebe0cf0e9 385 return buf + sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 386 }
ashleymills 0:ff9ebe0cf0e9 387
ashleymills 0:ff9ebe0cf0e9 388 /**
ashleymills 0:ff9ebe0cf0e9 389 * Initializes \p buf as handshake header. The caller must ensure that \p
ashleymills 0:ff9ebe0cf0e9 390 * buf is capable of holding at least \c sizeof(dtls_handshake_header_t)
ashleymills 0:ff9ebe0cf0e9 391 * bytes. Increments message sequence number counter of \p peer.
ashleymills 0:ff9ebe0cf0e9 392 * \return pointer to the next byte after \p buf
ashleymills 0:ff9ebe0cf0e9 393 */
ashleymills 0:ff9ebe0cf0e9 394 static inline uint8 *
ashleymills 0:ff9ebe0cf0e9 395 dtls_set_handshake_header(uint8 type, dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 396 int length,
ashleymills 0:ff9ebe0cf0e9 397 int frag_offset, int frag_length,
ashleymills 0:ff9ebe0cf0e9 398 uint8 *buf) {
ashleymills 0:ff9ebe0cf0e9 399
ashleymills 0:ff9ebe0cf0e9 400 dtls_int_to_uint8(buf, type);
ashleymills 0:ff9ebe0cf0e9 401 buf += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 402
ashleymills 0:ff9ebe0cf0e9 403 dtls_int_to_uint24(buf, length);
ashleymills 0:ff9ebe0cf0e9 404 buf += sizeof(uint24);
ashleymills 0:ff9ebe0cf0e9 405
ashleymills 0:ff9ebe0cf0e9 406 if (peer) {
ashleymills 0:ff9ebe0cf0e9 407 /* increment handshake message sequence counter by 1 */
ashleymills 0:ff9ebe0cf0e9 408 inc_uint(uint16, peer->hs_state.mseq);
ashleymills 0:ff9ebe0cf0e9 409
ashleymills 0:ff9ebe0cf0e9 410 /* and copy the result to buf */
ashleymills 0:ff9ebe0cf0e9 411 memcpy(buf, &peer->hs_state.mseq, sizeof(uint16));
ashleymills 0:ff9ebe0cf0e9 412 } else {
ashleymills 0:ff9ebe0cf0e9 413 memset(buf, 0, sizeof(uint16));
ashleymills 0:ff9ebe0cf0e9 414 }
ashleymills 0:ff9ebe0cf0e9 415 buf += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 416
ashleymills 0:ff9ebe0cf0e9 417 dtls_int_to_uint24(buf, frag_offset);
ashleymills 0:ff9ebe0cf0e9 418 buf += sizeof(uint24);
ashleymills 0:ff9ebe0cf0e9 419
ashleymills 0:ff9ebe0cf0e9 420 dtls_int_to_uint24(buf, frag_length);
ashleymills 0:ff9ebe0cf0e9 421 buf += sizeof(uint24);
ashleymills 0:ff9ebe0cf0e9 422
ashleymills 0:ff9ebe0cf0e9 423 return buf;
ashleymills 0:ff9ebe0cf0e9 424 }
ashleymills 0:ff9ebe0cf0e9 425
ashleymills 0:ff9ebe0cf0e9 426 /** only one compression method is currently defined */
ashleymills 0:ff9ebe0cf0e9 427 static uint8 compression_methods[] = {
ashleymills 0:ff9ebe0cf0e9 428 TLS_COMPRESSION_NULL
ashleymills 0:ff9ebe0cf0e9 429 };
ashleymills 0:ff9ebe0cf0e9 430
ashleymills 0:ff9ebe0cf0e9 431 static inline int is_psk_supported(dtls_context_t *ctx){
ashleymills 0:ff9ebe0cf0e9 432 return ctx && ctx->h && ctx->h->get_psk_key;
ashleymills 0:ff9ebe0cf0e9 433 }
ashleymills 0:ff9ebe0cf0e9 434
ashleymills 0:ff9ebe0cf0e9 435 static inline int is_ecdsa_supported(dtls_context_t *ctx, int is_client){
ashleymills 0:ff9ebe0cf0e9 436 return ctx && ctx->h && ((!is_client && ctx->h->get_ecdsa_key) ||
ashleymills 0:ff9ebe0cf0e9 437 (is_client && ctx->h->verify_ecdsa_key));
ashleymills 0:ff9ebe0cf0e9 438 }
ashleymills 0:ff9ebe0cf0e9 439
ashleymills 0:ff9ebe0cf0e9 440 /**
ashleymills 0:ff9ebe0cf0e9 441 * Returns @c 1 if @p code is a cipher suite other than @c
ashleymills 0:ff9ebe0cf0e9 442 * TLS_NULL_WITH_NULL_NULL that we recognize.
ashleymills 0:ff9ebe0cf0e9 443 *
ashleymills 0:ff9ebe0cf0e9 444 * @param ctx The current DTLS context
ashleymills 0:ff9ebe0cf0e9 445 * @param code The cipher suite identifier to check
ashleymills 0:ff9ebe0cf0e9 446 * @param is_client 1 for a dtls client, 0 for server
ashleymills 0:ff9ebe0cf0e9 447 * @return @c 1 iff @p code is recognized,
ashleymills 0:ff9ebe0cf0e9 448 */
ashleymills 0:ff9ebe0cf0e9 449 static int
ashleymills 0:ff9ebe0cf0e9 450 known_cipher(dtls_context_t *ctx, dtls_cipher_t code, int is_client) {
ashleymills 0:ff9ebe0cf0e9 451 int psk;
ashleymills 0:ff9ebe0cf0e9 452 int ecdsa;
ashleymills 0:ff9ebe0cf0e9 453
ashleymills 0:ff9ebe0cf0e9 454 psk = is_psk_supported(ctx);
ashleymills 0:ff9ebe0cf0e9 455 ecdsa = is_ecdsa_supported(ctx, is_client);
ashleymills 0:ff9ebe0cf0e9 456 return (psk && code == TLS_PSK_WITH_AES_128_CCM_8) ||
ashleymills 0:ff9ebe0cf0e9 457 (ecdsa && code == TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
ashleymills 0:ff9ebe0cf0e9 458 }
ashleymills 0:ff9ebe0cf0e9 459
ashleymills 0:ff9ebe0cf0e9 460 static void dtls_debug_keyblock(dtls_security_parameters_t *config)
ashleymills 0:ff9ebe0cf0e9 461 {
ashleymills 0:ff9ebe0cf0e9 462 DBG("key_block (%d bytes):", dtls_kb_size(config, peer->role));
ashleymills 0:ff9ebe0cf0e9 463 dtls_dsrv_hexdump_log(LOG_DEBUG, " client_MAC_secret",
ashleymills 0:ff9ebe0cf0e9 464 dtls_kb_client_mac_secret(config, peer->role),
ashleymills 0:ff9ebe0cf0e9 465 dtls_kb_mac_secret_size(config, peer->role), 0);
ashleymills 0:ff9ebe0cf0e9 466
ashleymills 0:ff9ebe0cf0e9 467 dtls_dsrv_hexdump_log(LOG_DEBUG, " server_MAC_secret",
ashleymills 0:ff9ebe0cf0e9 468 dtls_kb_server_mac_secret(config, peer->role),
ashleymills 0:ff9ebe0cf0e9 469 dtls_kb_mac_secret_size(config, peer->role), 0);
ashleymills 0:ff9ebe0cf0e9 470
ashleymills 0:ff9ebe0cf0e9 471 dtls_dsrv_hexdump_log(LOG_DEBUG, " client_write_key",
ashleymills 0:ff9ebe0cf0e9 472 dtls_kb_client_write_key(config, peer->role),
ashleymills 0:ff9ebe0cf0e9 473 dtls_kb_key_size(config, peer->role), 0);
ashleymills 0:ff9ebe0cf0e9 474
ashleymills 0:ff9ebe0cf0e9 475 dtls_dsrv_hexdump_log(LOG_DEBUG, " server_write_key",
ashleymills 0:ff9ebe0cf0e9 476 dtls_kb_server_write_key(config, peer->role),
ashleymills 0:ff9ebe0cf0e9 477 dtls_kb_key_size(config, peer->role), 0);
ashleymills 0:ff9ebe0cf0e9 478
ashleymills 0:ff9ebe0cf0e9 479 dtls_dsrv_hexdump_log(LOG_DEBUG, " client_IV",
ashleymills 0:ff9ebe0cf0e9 480 dtls_kb_client_iv(config, peer->role),
ashleymills 0:ff9ebe0cf0e9 481 dtls_kb_iv_size(config, peer->role), 0);
ashleymills 0:ff9ebe0cf0e9 482
ashleymills 0:ff9ebe0cf0e9 483 dtls_dsrv_hexdump_log(LOG_DEBUG, " server_IV",
ashleymills 0:ff9ebe0cf0e9 484 dtls_kb_server_iv(config, peer->role),
ashleymills 0:ff9ebe0cf0e9 485 dtls_kb_iv_size(config, peer->role), 0);
ashleymills 0:ff9ebe0cf0e9 486 }
ashleymills 0:ff9ebe0cf0e9 487
ashleymills 0:ff9ebe0cf0e9 488 static int
ashleymills 0:ff9ebe0cf0e9 489 calculate_key_block(dtls_context_t *ctx,
ashleymills 0:ff9ebe0cf0e9 490 dtls_handshake_parameters_t *handshake,
ashleymills 0:ff9ebe0cf0e9 491 dtls_security_parameters_t *security,
ashleymills 0:ff9ebe0cf0e9 492 session_t *session) {
ashleymills 0:ff9ebe0cf0e9 493 unsigned char *pre_master_secret;
ashleymills 0:ff9ebe0cf0e9 494 size_t pre_master_len = 0;
ashleymills 0:ff9ebe0cf0e9 495 pre_master_secret = security->key_block;
ashleymills 0:ff9ebe0cf0e9 496 uint8 master_secret[DTLS_MASTER_SECRET_LENGTH];
ashleymills 0:ff9ebe0cf0e9 497 int err;
ashleymills 0:ff9ebe0cf0e9 498
ashleymills 0:ff9ebe0cf0e9 499 switch (handshake->cipher) {
ashleymills 0:ff9ebe0cf0e9 500 case TLS_PSK_WITH_AES_128_CCM_8: {
ashleymills 0:ff9ebe0cf0e9 501 const dtls_psk_key_t *psk;
ashleymills 0:ff9ebe0cf0e9 502
ashleymills 0:ff9ebe0cf0e9 503 err = CALL(ctx, get_psk_key, session, handshake->keyx.psk.identity,
ashleymills 0:ff9ebe0cf0e9 504 handshake->keyx.psk.id_length, &psk);
ashleymills 0:ff9ebe0cf0e9 505 if (err < 0) {
ashleymills 0:ff9ebe0cf0e9 506 DBG("no psk key for session available");
ashleymills 0:ff9ebe0cf0e9 507 return err;
ashleymills 0:ff9ebe0cf0e9 508 }
ashleymills 0:ff9ebe0cf0e9 509 /* Temporarily use the key_block storage space for the pre master secret. */
ashleymills 0:ff9ebe0cf0e9 510 pre_master_len = dtls_psk_pre_master_secret(psk->key, psk->key_length,
ashleymills 0:ff9ebe0cf0e9 511 pre_master_secret);
ashleymills 0:ff9ebe0cf0e9 512
ashleymills 0:ff9ebe0cf0e9 513 dtls_dsrv_hexdump_log(LOG_DEBUG, "psk", psk->key, psk->key_length, 1);
ashleymills 0:ff9ebe0cf0e9 514
ashleymills 0:ff9ebe0cf0e9 515 break;
ashleymills 0:ff9ebe0cf0e9 516 }
ashleymills 0:ff9ebe0cf0e9 517 case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: {
ashleymills 0:ff9ebe0cf0e9 518 pre_master_len = dtls_ecdh_pre_master_secret(handshake->keyx.ecdsa.own_eph_priv,
ashleymills 0:ff9ebe0cf0e9 519 handshake->keyx.ecdsa.other_eph_pub_x,
ashleymills 0:ff9ebe0cf0e9 520 handshake->keyx.ecdsa.other_eph_pub_y,
ashleymills 0:ff9ebe0cf0e9 521 sizeof(handshake->keyx.ecdsa.own_eph_priv),
ashleymills 0:ff9ebe0cf0e9 522 pre_master_secret);
ashleymills 0:ff9ebe0cf0e9 523 break;
ashleymills 0:ff9ebe0cf0e9 524 }
ashleymills 0:ff9ebe0cf0e9 525 default:
ashleymills 0:ff9ebe0cf0e9 526 DBG("calculate_key_block: unknown cipher");
ashleymills 0:ff9ebe0cf0e9 527 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
ashleymills 0:ff9ebe0cf0e9 528 }
ashleymills 0:ff9ebe0cf0e9 529
ashleymills 0:ff9ebe0cf0e9 530 dtls_dsrv_hexdump_log(LOG_DEBUG, "client_random", handshake->tmp.random.client,
ashleymills 0:ff9ebe0cf0e9 531 DTLS_RANDOM_LENGTH, 0);
ashleymills 0:ff9ebe0cf0e9 532 dtls_dsrv_hexdump_log(LOG_DEBUG, "server_random", handshake->tmp.random.server,
ashleymills 0:ff9ebe0cf0e9 533 DTLS_RANDOM_LENGTH, 0);
ashleymills 0:ff9ebe0cf0e9 534 dtls_dsrv_hexdump_log(LOG_DEBUG, "pre_master_secret", pre_master_secret,
ashleymills 0:ff9ebe0cf0e9 535 pre_master_len, 0);
ashleymills 0:ff9ebe0cf0e9 536
ashleymills 0:ff9ebe0cf0e9 537 dtls_prf(pre_master_secret, pre_master_len,
ashleymills 0:ff9ebe0cf0e9 538 PRF_LABEL(master), PRF_LABEL_SIZE(master),
ashleymills 0:ff9ebe0cf0e9 539 handshake->tmp.random.client, DTLS_RANDOM_LENGTH,
ashleymills 0:ff9ebe0cf0e9 540 handshake->tmp.random.server, DTLS_RANDOM_LENGTH,
ashleymills 0:ff9ebe0cf0e9 541 master_secret,
ashleymills 0:ff9ebe0cf0e9 542 DTLS_MASTER_SECRET_LENGTH);
ashleymills 0:ff9ebe0cf0e9 543
ashleymills 0:ff9ebe0cf0e9 544 dtls_dsrv_hexdump_log(LOG_DEBUG, "master_secret", master_secret,
ashleymills 0:ff9ebe0cf0e9 545 DTLS_MASTER_SECRET_LENGTH, 0);
ashleymills 0:ff9ebe0cf0e9 546
ashleymills 0:ff9ebe0cf0e9 547 /* create key_block from master_secret
ashleymills 0:ff9ebe0cf0e9 548 * key_block = PRF(master_secret,
ashleymills 0:ff9ebe0cf0e9 549 "key expansion" + tmp.random.server + tmp.random.client) */
ashleymills 0:ff9ebe0cf0e9 550
ashleymills 0:ff9ebe0cf0e9 551 dtls_prf(master_secret,
ashleymills 0:ff9ebe0cf0e9 552 DTLS_MASTER_SECRET_LENGTH,
ashleymills 0:ff9ebe0cf0e9 553 PRF_LABEL(key), PRF_LABEL_SIZE(key),
ashleymills 0:ff9ebe0cf0e9 554 handshake->tmp.random.server, DTLS_RANDOM_LENGTH,
ashleymills 0:ff9ebe0cf0e9 555 handshake->tmp.random.client, DTLS_RANDOM_LENGTH,
ashleymills 0:ff9ebe0cf0e9 556 security->key_block,
ashleymills 0:ff9ebe0cf0e9 557 dtls_kb_size(security, peer->role));
ashleymills 0:ff9ebe0cf0e9 558
ashleymills 0:ff9ebe0cf0e9 559 memcpy(handshake->tmp.master_secret, master_secret, DTLS_MASTER_SECRET_LENGTH);
ashleymills 0:ff9ebe0cf0e9 560 dtls_debug_keyblock(security);
ashleymills 0:ff9ebe0cf0e9 561 return 0;
ashleymills 0:ff9ebe0cf0e9 562 }
ashleymills 0:ff9ebe0cf0e9 563
ashleymills 0:ff9ebe0cf0e9 564 /**
ashleymills 0:ff9ebe0cf0e9 565 * Releases the storage allocated for read_cipher and write_cipher and
ashleymills 0:ff9ebe0cf0e9 566 * sets both fields to NULL.
ashleymills 0:ff9ebe0cf0e9 567 */
ashleymills 0:ff9ebe0cf0e9 568 static void
ashleymills 0:ff9ebe0cf0e9 569 invalidate_ciphers(dtls_security_parameters_t *config) {
ashleymills 0:ff9ebe0cf0e9 570 if (config->read_cipher) {
ashleymills 0:ff9ebe0cf0e9 571 dtls_cipher_free(config->read_cipher);
ashleymills 0:ff9ebe0cf0e9 572 config->read_cipher = NULL;
ashleymills 0:ff9ebe0cf0e9 573 }
ashleymills 0:ff9ebe0cf0e9 574
ashleymills 0:ff9ebe0cf0e9 575 if (config->write_cipher) {
ashleymills 0:ff9ebe0cf0e9 576 dtls_cipher_free(config->write_cipher);
ashleymills 0:ff9ebe0cf0e9 577 config->write_cipher = NULL;
ashleymills 0:ff9ebe0cf0e9 578 }
ashleymills 0:ff9ebe0cf0e9 579 }
ashleymills 0:ff9ebe0cf0e9 580
ashleymills 0:ff9ebe0cf0e9 581 static int
ashleymills 0:ff9ebe0cf0e9 582 init_cipher(dtls_handshake_parameters_t *handshake, dtls_security_parameters_t *config, dtls_peer_type role)
ashleymills 0:ff9ebe0cf0e9 583 {
ashleymills 0:ff9ebe0cf0e9 584 /* set crypto context for TLS_PSK_WITH_AES_128_CCM_8 */
ashleymills 0:ff9ebe0cf0e9 585 dtls_cipher_free(config->read_cipher);
ashleymills 0:ff9ebe0cf0e9 586
ashleymills 0:ff9ebe0cf0e9 587 assert(handshake->cipher != TLS_NULL_WITH_NULL_NULL);
ashleymills 0:ff9ebe0cf0e9 588 config->read_cipher = dtls_cipher_new(handshake->cipher,
ashleymills 0:ff9ebe0cf0e9 589 dtls_kb_remote_write_key(config, role),
ashleymills 0:ff9ebe0cf0e9 590 dtls_kb_key_size(config, role));
ashleymills 0:ff9ebe0cf0e9 591
ashleymills 0:ff9ebe0cf0e9 592 if (!config->read_cipher) {
ashleymills 0:ff9ebe0cf0e9 593 WARN("cannot create read cipher");
ashleymills 0:ff9ebe0cf0e9 594 goto error;
ashleymills 0:ff9ebe0cf0e9 595 }
ashleymills 0:ff9ebe0cf0e9 596
ashleymills 0:ff9ebe0cf0e9 597 dtls_cipher_free(config->write_cipher);
ashleymills 0:ff9ebe0cf0e9 598
ashleymills 0:ff9ebe0cf0e9 599 config->write_cipher = dtls_cipher_new(handshake->cipher,
ashleymills 0:ff9ebe0cf0e9 600 dtls_kb_local_write_key(config, role),
ashleymills 0:ff9ebe0cf0e9 601 dtls_kb_key_size(config, role));
ashleymills 0:ff9ebe0cf0e9 602
ashleymills 0:ff9ebe0cf0e9 603 if (!config->write_cipher) {
ashleymills 0:ff9ebe0cf0e9 604 WARN("cannot create write cipher");
ashleymills 0:ff9ebe0cf0e9 605 goto error;
ashleymills 0:ff9ebe0cf0e9 606 }
ashleymills 0:ff9ebe0cf0e9 607
ashleymills 0:ff9ebe0cf0e9 608 config->cipher = handshake->cipher;
ashleymills 0:ff9ebe0cf0e9 609 config->compression = handshake->compression;
ashleymills 0:ff9ebe0cf0e9 610
ashleymills 0:ff9ebe0cf0e9 611 return 0;
ashleymills 0:ff9ebe0cf0e9 612 error:
ashleymills 0:ff9ebe0cf0e9 613
ashleymills 0:ff9ebe0cf0e9 614 invalidate_ciphers(config);
ashleymills 0:ff9ebe0cf0e9 615 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
ashleymills 0:ff9ebe0cf0e9 616 }
ashleymills 0:ff9ebe0cf0e9 617
ashleymills 0:ff9ebe0cf0e9 618 /* TODO: add a generic method which iterates over a list and searches for a specific key */
ashleymills 0:ff9ebe0cf0e9 619 static int verify_ext_eliptic_curves(uint8 *data, size_t data_length) {
ashleymills 0:ff9ebe0cf0e9 620 int i, curve_name;
ashleymills 0:ff9ebe0cf0e9 621
ashleymills 0:ff9ebe0cf0e9 622 /* length of curve list */
ashleymills 0:ff9ebe0cf0e9 623 i = dtls_uint16_to_int(data);
ashleymills 0:ff9ebe0cf0e9 624 data += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 625 if (i + sizeof(uint16) != data_length) {
ashleymills 0:ff9ebe0cf0e9 626 WARN("the list of the supported elliptic curves should be tls extension length - 2");
ashleymills 0:ff9ebe0cf0e9 627 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 628 }
ashleymills 0:ff9ebe0cf0e9 629
ashleymills 0:ff9ebe0cf0e9 630 for (i = data_length - sizeof(uint16); i > 0; i -= sizeof(uint16)) {
ashleymills 0:ff9ebe0cf0e9 631 /* check if this curve is supported */
ashleymills 0:ff9ebe0cf0e9 632 curve_name = dtls_uint16_to_int(data);
ashleymills 0:ff9ebe0cf0e9 633 data += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 634
ashleymills 0:ff9ebe0cf0e9 635 if (curve_name == TLS_EXT_ELLIPTIC_CURVES_SECP256R1)
ashleymills 0:ff9ebe0cf0e9 636 return 0;
ashleymills 0:ff9ebe0cf0e9 637 }
ashleymills 0:ff9ebe0cf0e9 638
ashleymills 0:ff9ebe0cf0e9 639 WARN("no supported elliptic curve found");
ashleymills 0:ff9ebe0cf0e9 640 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 641 }
ashleymills 0:ff9ebe0cf0e9 642
ashleymills 0:ff9ebe0cf0e9 643 static int verify_ext_cert_type(uint8 *data, size_t data_length) {
ashleymills 0:ff9ebe0cf0e9 644 int i, cert_type;
ashleymills 0:ff9ebe0cf0e9 645
ashleymills 0:ff9ebe0cf0e9 646 /* length of cert type list */
ashleymills 0:ff9ebe0cf0e9 647 i = dtls_uint8_to_int(data);
ashleymills 0:ff9ebe0cf0e9 648 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 649 if (i + sizeof(uint8) != data_length) {
ashleymills 0:ff9ebe0cf0e9 650 WARN("the list of the supported certificate types should be tls extension length - 1");
ashleymills 0:ff9ebe0cf0e9 651 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 652 }
ashleymills 0:ff9ebe0cf0e9 653
ashleymills 0:ff9ebe0cf0e9 654 for (i = data_length - sizeof(uint8); i > 0; i -= sizeof(uint8)) {
ashleymills 0:ff9ebe0cf0e9 655 /* check if this cert type is supported */
ashleymills 0:ff9ebe0cf0e9 656 cert_type = dtls_uint8_to_int(data);
ashleymills 0:ff9ebe0cf0e9 657 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 658
ashleymills 0:ff9ebe0cf0e9 659 if (cert_type == TLS_CERT_TYPE_OOB)
ashleymills 0:ff9ebe0cf0e9 660 return 0;
ashleymills 0:ff9ebe0cf0e9 661 }
ashleymills 0:ff9ebe0cf0e9 662
ashleymills 0:ff9ebe0cf0e9 663 WARN("no supported certificate type found");
ashleymills 0:ff9ebe0cf0e9 664 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 665 }
ashleymills 0:ff9ebe0cf0e9 666
ashleymills 0:ff9ebe0cf0e9 667 static int verify_ext_ec_point_formats(uint8 *data, size_t data_length) {
ashleymills 0:ff9ebe0cf0e9 668 int i, cert_type;
ashleymills 0:ff9ebe0cf0e9 669
ashleymills 0:ff9ebe0cf0e9 670 /* length of ec_point_formats list */
ashleymills 0:ff9ebe0cf0e9 671 i = dtls_uint8_to_int(data);
ashleymills 0:ff9ebe0cf0e9 672 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 673 if (i + sizeof(uint8) != data_length) {
ashleymills 0:ff9ebe0cf0e9 674 WARN("the list of the supported ec_point_formats should be tls extension length - 1");
ashleymills 0:ff9ebe0cf0e9 675 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 676 }
ashleymills 0:ff9ebe0cf0e9 677
ashleymills 0:ff9ebe0cf0e9 678 for (i = data_length - sizeof(uint8); i > 0; i -= sizeof(uint8)) {
ashleymills 0:ff9ebe0cf0e9 679 /* check if this ec_point_format is supported */
ashleymills 0:ff9ebe0cf0e9 680 cert_type = dtls_uint8_to_int(data);
ashleymills 0:ff9ebe0cf0e9 681 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 682
ashleymills 0:ff9ebe0cf0e9 683 if (cert_type == TLS_EXT_EC_POINT_FORMATS_UNCOMPRESSED)
ashleymills 0:ff9ebe0cf0e9 684 return 0;
ashleymills 0:ff9ebe0cf0e9 685 }
ashleymills 0:ff9ebe0cf0e9 686
ashleymills 0:ff9ebe0cf0e9 687 WARN("no supported ec_point_format found");
ashleymills 0:ff9ebe0cf0e9 688 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 689 }
ashleymills 0:ff9ebe0cf0e9 690
ashleymills 0:ff9ebe0cf0e9 691 static int
ashleymills 0:ff9ebe0cf0e9 692 dtls_check_tls_extension(dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 693 uint8 *data, size_t data_length, int client_hello)
ashleymills 0:ff9ebe0cf0e9 694 {
ashleymills 0:ff9ebe0cf0e9 695 int i, j;
ashleymills 0:ff9ebe0cf0e9 696 int ext_elliptic_curve = 0;
ashleymills 0:ff9ebe0cf0e9 697 int ext_client_cert_type = 0;
ashleymills 0:ff9ebe0cf0e9 698 int ext_server_cert_type = 0;
ashleymills 0:ff9ebe0cf0e9 699 int ext_ec_point_formats = 0;
ashleymills 0:ff9ebe0cf0e9 700 dtls_handshake_parameters_t *handshake = &peer->handshake_params;
ashleymills 0:ff9ebe0cf0e9 701
ashleymills 0:ff9ebe0cf0e9 702 if (data_length < sizeof(uint16)) {
ashleymills 0:ff9ebe0cf0e9 703 /* no tls extensions specified */
ashleymills 0:ff9ebe0cf0e9 704 if (handshake->cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8) {
ashleymills 0:ff9ebe0cf0e9 705 goto error;
ashleymills 0:ff9ebe0cf0e9 706 }
ashleymills 0:ff9ebe0cf0e9 707 return 0;
ashleymills 0:ff9ebe0cf0e9 708 }
ashleymills 0:ff9ebe0cf0e9 709
ashleymills 0:ff9ebe0cf0e9 710 /* get the length of the tls extension list */
ashleymills 0:ff9ebe0cf0e9 711 j = dtls_uint16_to_int(data);
ashleymills 0:ff9ebe0cf0e9 712 data += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 713 data_length -= sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 714
ashleymills 0:ff9ebe0cf0e9 715 if (data_length < j)
ashleymills 0:ff9ebe0cf0e9 716 goto error;
ashleymills 0:ff9ebe0cf0e9 717
ashleymills 0:ff9ebe0cf0e9 718 /* check for TLS extensions needed for this cipher */
ashleymills 0:ff9ebe0cf0e9 719 while (data_length) {
ashleymills 0:ff9ebe0cf0e9 720 if (data_length < sizeof(uint16) * 2)
ashleymills 0:ff9ebe0cf0e9 721 goto error;
ashleymills 0:ff9ebe0cf0e9 722
ashleymills 0:ff9ebe0cf0e9 723 /* get the tls extension type */
ashleymills 0:ff9ebe0cf0e9 724 i = dtls_uint16_to_int(data);
ashleymills 0:ff9ebe0cf0e9 725 data += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 726 data_length -= sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 727
ashleymills 0:ff9ebe0cf0e9 728 /* get the length of the tls extension */
ashleymills 0:ff9ebe0cf0e9 729 j = dtls_uint16_to_int(data);
ashleymills 0:ff9ebe0cf0e9 730 data += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 731 data_length -= sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 732
ashleymills 0:ff9ebe0cf0e9 733 if (data_length < j)
ashleymills 0:ff9ebe0cf0e9 734 goto error;
ashleymills 0:ff9ebe0cf0e9 735
ashleymills 0:ff9ebe0cf0e9 736 switch (i) {
ashleymills 0:ff9ebe0cf0e9 737 case TLS_EXT_ELLIPTIC_CURVES:
ashleymills 0:ff9ebe0cf0e9 738 ext_elliptic_curve = 1;
ashleymills 0:ff9ebe0cf0e9 739 if (verify_ext_eliptic_curves(data, j))
ashleymills 0:ff9ebe0cf0e9 740 goto error;
ashleymills 0:ff9ebe0cf0e9 741 break;
ashleymills 0:ff9ebe0cf0e9 742 case TLS_EXT_CLIENT_CERIFICATE_TYPE:
ashleymills 0:ff9ebe0cf0e9 743 ext_client_cert_type = 1;
ashleymills 0:ff9ebe0cf0e9 744 if (client_hello) {
ashleymills 0:ff9ebe0cf0e9 745 if (verify_ext_cert_type(data, j))
ashleymills 0:ff9ebe0cf0e9 746 goto error;
ashleymills 0:ff9ebe0cf0e9 747 } else {
ashleymills 0:ff9ebe0cf0e9 748 if (dtls_uint8_to_int(data) != TLS_CERT_TYPE_OOB)
ashleymills 0:ff9ebe0cf0e9 749 goto error;
ashleymills 0:ff9ebe0cf0e9 750 }
ashleymills 0:ff9ebe0cf0e9 751 break;
ashleymills 0:ff9ebe0cf0e9 752 case TLS_EXT_SERVER_CERIFICATE_TYPE:
ashleymills 0:ff9ebe0cf0e9 753 ext_server_cert_type = 1;
ashleymills 0:ff9ebe0cf0e9 754 if (client_hello) {
ashleymills 0:ff9ebe0cf0e9 755 if (verify_ext_cert_type(data, j))
ashleymills 0:ff9ebe0cf0e9 756 goto error;
ashleymills 0:ff9ebe0cf0e9 757 } else {
ashleymills 0:ff9ebe0cf0e9 758 if (dtls_uint8_to_int(data) != TLS_CERT_TYPE_OOB)
ashleymills 0:ff9ebe0cf0e9 759 goto error;
ashleymills 0:ff9ebe0cf0e9 760 }
ashleymills 0:ff9ebe0cf0e9 761 break;
ashleymills 0:ff9ebe0cf0e9 762 case TLS_EXT_EC_POINT_FORMATS:
ashleymills 0:ff9ebe0cf0e9 763 ext_ec_point_formats = 1;
ashleymills 0:ff9ebe0cf0e9 764 if (verify_ext_ec_point_formats(data, j))
ashleymills 0:ff9ebe0cf0e9 765 goto error;
ashleymills 0:ff9ebe0cf0e9 766 break;
ashleymills 0:ff9ebe0cf0e9 767 default:
ashleymills 0:ff9ebe0cf0e9 768 WARN("unsupported tls extension: %i", i);
ashleymills 0:ff9ebe0cf0e9 769 break;
ashleymills 0:ff9ebe0cf0e9 770 }
ashleymills 0:ff9ebe0cf0e9 771 data += j;
ashleymills 0:ff9ebe0cf0e9 772 data_length -= j;
ashleymills 0:ff9ebe0cf0e9 773 }
ashleymills 0:ff9ebe0cf0e9 774 if (handshake->cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8) {
ashleymills 0:ff9ebe0cf0e9 775 if (!ext_elliptic_curve && !ext_client_cert_type && !ext_server_cert_type
ashleymills 0:ff9ebe0cf0e9 776 && !ext_ec_point_formats) {
ashleymills 0:ff9ebe0cf0e9 777 WARN("not all required tls extensions found in client hello");
ashleymills 0:ff9ebe0cf0e9 778 goto error;
ashleymills 0:ff9ebe0cf0e9 779 }
ashleymills 0:ff9ebe0cf0e9 780 }
ashleymills 0:ff9ebe0cf0e9 781 return 0;
ashleymills 0:ff9ebe0cf0e9 782
ashleymills 0:ff9ebe0cf0e9 783 error:
ashleymills 0:ff9ebe0cf0e9 784 if (client_hello && peer->state == DTLS_STATE_CONNECTED) {
ashleymills 0:ff9ebe0cf0e9 785 return dtls_alert_create(DTLS_ALERT_LEVEL_WARNING, DTLS_ALERT_NO_RENEGOTIATION);
ashleymills 0:ff9ebe0cf0e9 786 } else {
ashleymills 0:ff9ebe0cf0e9 787 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 788 }
ashleymills 0:ff9ebe0cf0e9 789 }
ashleymills 0:ff9ebe0cf0e9 790
ashleymills 0:ff9ebe0cf0e9 791 /**
ashleymills 0:ff9ebe0cf0e9 792 * Updates the security parameters of given \p peer. As this must be
ashleymills 0:ff9ebe0cf0e9 793 * done before the new configuration is activated, it changes the
ashleymills 0:ff9ebe0cf0e9 794 * OTHER_CONFIG only. When the ClientHello handshake message in \p
ashleymills 0:ff9ebe0cf0e9 795 * data does not contain a cipher suite or compression method, it is
ashleymills 0:ff9ebe0cf0e9 796 * copied from the CURRENT_CONFIG.
ashleymills 0:ff9ebe0cf0e9 797 *
ashleymills 0:ff9ebe0cf0e9 798 * \param ctx The current DTLS context.
ashleymills 0:ff9ebe0cf0e9 799 * \param peer The remote peer whose security parameters are about to change.
ashleymills 0:ff9ebe0cf0e9 800 * \param data The handshake message with a ClientHello.
ashleymills 0:ff9ebe0cf0e9 801 * \param data_length The actual size of \p data.
ashleymills 0:ff9ebe0cf0e9 802 * \return \c 0 if an error occurred, \c 1 otherwise.
ashleymills 0:ff9ebe0cf0e9 803 */
ashleymills 0:ff9ebe0cf0e9 804 static int
ashleymills 0:ff9ebe0cf0e9 805 dtls_update_parameters(dtls_context_t *ctx,
ashleymills 0:ff9ebe0cf0e9 806 dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 807 uint8 *data, size_t data_length) {
ashleymills 0:ff9ebe0cf0e9 808 int i, j;
ashleymills 0:ff9ebe0cf0e9 809 int ok;
ashleymills 0:ff9ebe0cf0e9 810 dtls_handshake_parameters_t *config = &peer->handshake_params;
ashleymills 0:ff9ebe0cf0e9 811 dtls_security_parameters_t *security = &peer->security_params;
ashleymills 0:ff9ebe0cf0e9 812
ashleymills 0:ff9ebe0cf0e9 813 assert(config);
ashleymills 0:ff9ebe0cf0e9 814 assert(data_length > DTLS_HS_LENGTH + DTLS_CH_LENGTH);
ashleymills 0:ff9ebe0cf0e9 815
ashleymills 0:ff9ebe0cf0e9 816 /* DBG("dtls_update_parameters: msglen is %d", data_length); */
ashleymills 0:ff9ebe0cf0e9 817
ashleymills 0:ff9ebe0cf0e9 818 /* skip the handshake header and client version information */
ashleymills 0:ff9ebe0cf0e9 819 data += DTLS_HS_LENGTH + sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 820 data_length -= DTLS_HS_LENGTH + sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 821
ashleymills 0:ff9ebe0cf0e9 822 /* store client random in config
ashleymills 0:ff9ebe0cf0e9 823 * FIXME: if we send the ServerHello here, we do not need to store
ashleymills 0:ff9ebe0cf0e9 824 * the client's random bytes */
ashleymills 0:ff9ebe0cf0e9 825 memcpy(config->tmp.random.client, data, DTLS_RANDOM_LENGTH);
ashleymills 0:ff9ebe0cf0e9 826 data += DTLS_RANDOM_LENGTH;
ashleymills 0:ff9ebe0cf0e9 827 data_length -= DTLS_RANDOM_LENGTH;
ashleymills 0:ff9ebe0cf0e9 828
ashleymills 0:ff9ebe0cf0e9 829 /* Caution: SKIP_VAR_FIELD may jump to error: */
ashleymills 0:ff9ebe0cf0e9 830 SKIP_VAR_FIELD(data, data_length, uint8); /* skip session id */
ashleymills 0:ff9ebe0cf0e9 831 SKIP_VAR_FIELD(data, data_length, uint8); /* skip cookie */
ashleymills 0:ff9ebe0cf0e9 832
ashleymills 0:ff9ebe0cf0e9 833 i = dtls_uint16_to_int(data);
ashleymills 0:ff9ebe0cf0e9 834 if (data_length < i + sizeof(uint16)) {
ashleymills 0:ff9ebe0cf0e9 835 /* Looks like we do not have a cipher nor compression. This is ok
ashleymills 0:ff9ebe0cf0e9 836 * for renegotiation, but not for the initial handshake. */
ashleymills 0:ff9ebe0cf0e9 837
ashleymills 0:ff9ebe0cf0e9 838 if (security->cipher == TLS_NULL_WITH_NULL_NULL)
ashleymills 0:ff9ebe0cf0e9 839 goto error;
ashleymills 0:ff9ebe0cf0e9 840
ashleymills 0:ff9ebe0cf0e9 841 config->cipher = security->cipher;
ashleymills 0:ff9ebe0cf0e9 842 config->compression = security->compression;
ashleymills 0:ff9ebe0cf0e9 843
ashleymills 0:ff9ebe0cf0e9 844 return 0;
ashleymills 0:ff9ebe0cf0e9 845 }
ashleymills 0:ff9ebe0cf0e9 846
ashleymills 0:ff9ebe0cf0e9 847 data += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 848 data_length -= sizeof(uint16) + i;
ashleymills 0:ff9ebe0cf0e9 849
ashleymills 0:ff9ebe0cf0e9 850 ok = 0;
ashleymills 0:ff9ebe0cf0e9 851 while (i && !ok) {
ashleymills 0:ff9ebe0cf0e9 852 config->cipher = dtls_uint16_to_int(data);
ashleymills 0:ff9ebe0cf0e9 853 ok = known_cipher(ctx, config->cipher, 0);
ashleymills 0:ff9ebe0cf0e9 854 i -= sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 855 data += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 856 }
ashleymills 0:ff9ebe0cf0e9 857
ashleymills 0:ff9ebe0cf0e9 858 /* skip remaining ciphers */
ashleymills 0:ff9ebe0cf0e9 859 data += i;
ashleymills 0:ff9ebe0cf0e9 860
ashleymills 0:ff9ebe0cf0e9 861 if (!ok) {
ashleymills 0:ff9ebe0cf0e9 862 /* reset config cipher to a well-defined value */
ashleymills 0:ff9ebe0cf0e9 863 config->cipher = TLS_NULL_WITH_NULL_NULL;
ashleymills 0:ff9ebe0cf0e9 864 goto error;
ashleymills 0:ff9ebe0cf0e9 865 }
ashleymills 0:ff9ebe0cf0e9 866
ashleymills 0:ff9ebe0cf0e9 867 if (data_length < sizeof(uint8)) {
ashleymills 0:ff9ebe0cf0e9 868 /* no compression specified, take the current compression method */
ashleymills 0:ff9ebe0cf0e9 869 config->compression = security->compression;
ashleymills 0:ff9ebe0cf0e9 870 goto error;
ashleymills 0:ff9ebe0cf0e9 871 }
ashleymills 0:ff9ebe0cf0e9 872
ashleymills 0:ff9ebe0cf0e9 873 i = dtls_uint8_to_int(data);
ashleymills 0:ff9ebe0cf0e9 874 if (data_length < i + sizeof(uint8))
ashleymills 0:ff9ebe0cf0e9 875 goto error;
ashleymills 0:ff9ebe0cf0e9 876
ashleymills 0:ff9ebe0cf0e9 877 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 878 data_length -= sizeof(uint8) + i;
ashleymills 0:ff9ebe0cf0e9 879
ashleymills 0:ff9ebe0cf0e9 880 ok = 0;
ashleymills 0:ff9ebe0cf0e9 881 while (i && !ok) {
ashleymills 0:ff9ebe0cf0e9 882 for (j = 0; j < sizeof(compression_methods) / sizeof(uint8); ++j)
ashleymills 0:ff9ebe0cf0e9 883 if (dtls_uint8_to_int(data) == compression_methods[j]) {
ashleymills 0:ff9ebe0cf0e9 884 config->compression = compression_methods[j];
ashleymills 0:ff9ebe0cf0e9 885 ok = 1;
ashleymills 0:ff9ebe0cf0e9 886 }
ashleymills 0:ff9ebe0cf0e9 887 i -= sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 888 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 889 }
ashleymills 0:ff9ebe0cf0e9 890
ashleymills 0:ff9ebe0cf0e9 891 if (!ok) {
ashleymills 0:ff9ebe0cf0e9 892 /* reset config cipher to a well-defined value */
ashleymills 0:ff9ebe0cf0e9 893 goto error;
ashleymills 0:ff9ebe0cf0e9 894 }
ashleymills 0:ff9ebe0cf0e9 895
ashleymills 0:ff9ebe0cf0e9 896 return dtls_check_tls_extension(peer, data, data_length, 1);
ashleymills 0:ff9ebe0cf0e9 897 error:
ashleymills 0:ff9ebe0cf0e9 898 WARN("ClientHello too short (%d bytes)", data_length);
ashleymills 0:ff9ebe0cf0e9 899 if (peer->state == DTLS_STATE_CONNECTED) {
ashleymills 0:ff9ebe0cf0e9 900 return dtls_alert_create(DTLS_ALERT_LEVEL_WARNING, DTLS_ALERT_NO_RENEGOTIATION);
ashleymills 0:ff9ebe0cf0e9 901 } else {
ashleymills 0:ff9ebe0cf0e9 902 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 903 }
ashleymills 0:ff9ebe0cf0e9 904 }
ashleymills 0:ff9ebe0cf0e9 905
ashleymills 0:ff9ebe0cf0e9 906 static inline int
ashleymills 0:ff9ebe0cf0e9 907 check_client_keyexchange(dtls_context_t *ctx,
ashleymills 0:ff9ebe0cf0e9 908 dtls_handshake_parameters_t *handshake,
ashleymills 0:ff9ebe0cf0e9 909 uint8 *data, size_t length) {
ashleymills 0:ff9ebe0cf0e9 910
ashleymills 0:ff9ebe0cf0e9 911 if (handshake->cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8) {
ashleymills 0:ff9ebe0cf0e9 912
ashleymills 0:ff9ebe0cf0e9 913 if (length < DTLS_HS_LENGTH + DTLS_CKXEC_LENGTH) {
ashleymills 0:ff9ebe0cf0e9 914 DBG("The client key exchange is too short");
ashleymills 0:ff9ebe0cf0e9 915 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 916 }
ashleymills 0:ff9ebe0cf0e9 917 data += DTLS_HS_LENGTH;
ashleymills 0:ff9ebe0cf0e9 918
ashleymills 0:ff9ebe0cf0e9 919 if (dtls_uint8_to_int(data) != 65) {
ashleymills 0:ff9ebe0cf0e9 920 DBG("expected 65 bytes long public point");
ashleymills 0:ff9ebe0cf0e9 921 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 922 }
ashleymills 0:ff9ebe0cf0e9 923 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 924
ashleymills 0:ff9ebe0cf0e9 925 if (dtls_uint8_to_int(data) != 4) {
ashleymills 0:ff9ebe0cf0e9 926 DBG("expected uncompressed public point");
ashleymills 0:ff9ebe0cf0e9 927 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 928 }
ashleymills 0:ff9ebe0cf0e9 929 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 930
ashleymills 0:ff9ebe0cf0e9 931 memcpy(handshake->keyx.ecdsa.other_eph_pub_x, data,
ashleymills 0:ff9ebe0cf0e9 932 sizeof(handshake->keyx.ecdsa.other_eph_pub_x));
ashleymills 0:ff9ebe0cf0e9 933 data += sizeof(handshake->keyx.ecdsa.other_eph_pub_x);
ashleymills 0:ff9ebe0cf0e9 934
ashleymills 0:ff9ebe0cf0e9 935 memcpy(handshake->keyx.ecdsa.other_eph_pub_y, data,
ashleymills 0:ff9ebe0cf0e9 936 sizeof(handshake->keyx.ecdsa.other_eph_pub_y));
ashleymills 0:ff9ebe0cf0e9 937 data += sizeof(handshake->keyx.ecdsa.other_eph_pub_y);
ashleymills 0:ff9ebe0cf0e9 938 } else {
ashleymills 0:ff9ebe0cf0e9 939 int id_length;
ashleymills 0:ff9ebe0cf0e9 940
ashleymills 0:ff9ebe0cf0e9 941 if (length < DTLS_HS_LENGTH + DTLS_CKXPSK_LENGTH_MIN) {
ashleymills 0:ff9ebe0cf0e9 942 DBG("The client key exchange is too short");
ashleymills 0:ff9ebe0cf0e9 943 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 944 }
ashleymills 0:ff9ebe0cf0e9 945 data += DTLS_HS_LENGTH;
ashleymills 0:ff9ebe0cf0e9 946
ashleymills 0:ff9ebe0cf0e9 947 id_length = dtls_uint16_to_int(data);
ashleymills 0:ff9ebe0cf0e9 948 data += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 949
ashleymills 0:ff9ebe0cf0e9 950 if (DTLS_HS_LENGTH + DTLS_CKXPSK_LENGTH_MIN + id_length != length) {
ashleymills 0:ff9ebe0cf0e9 951 DBG("The identity has a wrong length");
ashleymills 0:ff9ebe0cf0e9 952 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 953 }
ashleymills 0:ff9ebe0cf0e9 954
ashleymills 0:ff9ebe0cf0e9 955 if (id_length > DTLS_PSK_MAX_CLIENT_IDENTITY_LEN) {
ashleymills 0:ff9ebe0cf0e9 956 WARN("please use a smaller client identity");
ashleymills 0:ff9ebe0cf0e9 957 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
ashleymills 0:ff9ebe0cf0e9 958 }
ashleymills 0:ff9ebe0cf0e9 959
ashleymills 0:ff9ebe0cf0e9 960 handshake->keyx.psk.id_length = id_length;
ashleymills 0:ff9ebe0cf0e9 961 memcpy(handshake->keyx.psk.identity, data, id_length);
ashleymills 0:ff9ebe0cf0e9 962 }
ashleymills 0:ff9ebe0cf0e9 963 return 0;
ashleymills 0:ff9ebe0cf0e9 964 }
ashleymills 0:ff9ebe0cf0e9 965
ashleymills 0:ff9ebe0cf0e9 966 static inline void
ashleymills 0:ff9ebe0cf0e9 967 update_hs_hash(dtls_peer_t *peer, uint8 *data, size_t length) {
ashleymills 0:ff9ebe0cf0e9 968 dtls_dsrv_hexdump_log(LOG_DEBUG, "add MAC data", data, length, 0);
ashleymills 0:ff9ebe0cf0e9 969 dtls_hash_update(&peer->hs_state.hs_hash, data, length);
ashleymills 0:ff9ebe0cf0e9 970 }
ashleymills 0:ff9ebe0cf0e9 971
ashleymills 0:ff9ebe0cf0e9 972 static void
ashleymills 0:ff9ebe0cf0e9 973 copy_hs_hash(dtls_peer_t *peer, dtls_hash_ctx *hs_hash) {
ashleymills 0:ff9ebe0cf0e9 974 memcpy(hs_hash, &peer->hs_state.hs_hash, sizeof(peer->hs_state.hs_hash));
ashleymills 0:ff9ebe0cf0e9 975 }
ashleymills 0:ff9ebe0cf0e9 976
ashleymills 0:ff9ebe0cf0e9 977 static inline size_t
ashleymills 0:ff9ebe0cf0e9 978 finalize_hs_hash(dtls_peer_t *peer, uint8 *buf) {
ashleymills 0:ff9ebe0cf0e9 979 return dtls_hash_finalize(buf, &peer->hs_state.hs_hash);
ashleymills 0:ff9ebe0cf0e9 980 }
ashleymills 0:ff9ebe0cf0e9 981
ashleymills 0:ff9ebe0cf0e9 982 static inline void
ashleymills 0:ff9ebe0cf0e9 983 clear_hs_hash(dtls_peer_t *peer) {
ashleymills 0:ff9ebe0cf0e9 984 assert(peer);
ashleymills 0:ff9ebe0cf0e9 985 DBG("clear MAC");
ashleymills 0:ff9ebe0cf0e9 986 dtls_hash_init(&peer->hs_state.hs_hash);
ashleymills 0:ff9ebe0cf0e9 987 }
ashleymills 0:ff9ebe0cf0e9 988
ashleymills 0:ff9ebe0cf0e9 989 /**
ashleymills 0:ff9ebe0cf0e9 990 *Checks if \p record + \p data contain a Finished message with valid
ashleymills 0:ff9ebe0cf0e9 991 * verify_data.
ashleymills 0:ff9ebe0cf0e9 992 *
ashleymills 0:ff9ebe0cf0e9 993 * \param ctx The current DTLS context.
ashleymills 0:ff9ebe0cf0e9 994 * \param peer The remote peer of the security association.
ashleymills 0:ff9ebe0cf0e9 995 * \param record The message record header.
ashleymills 0:ff9ebe0cf0e9 996 * \param rlen The actual length of \p record.
ashleymills 0:ff9ebe0cf0e9 997 * \param data The cleartext payload of the message.
ashleymills 0:ff9ebe0cf0e9 998 * \param data_length Actual length of \p data.
ashleymills 0:ff9ebe0cf0e9 999 * \return \c 1 if the Finished message is valid, \c 0 otherwise.
ashleymills 0:ff9ebe0cf0e9 1000 */
ashleymills 0:ff9ebe0cf0e9 1001 static int
ashleymills 0:ff9ebe0cf0e9 1002 check_finished(dtls_context_t *ctx, dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 1003 uint8 *record, uint8 *data, size_t data_length) {
ashleymills 0:ff9ebe0cf0e9 1004
ashleymills 0:ff9ebe0cf0e9 1005 DBG("check_finished");
ashleymills 0:ff9ebe0cf0e9 1006 size_t digest_length, label_size;
ashleymills 0:ff9ebe0cf0e9 1007 const unsigned char *label;
ashleymills 0:ff9ebe0cf0e9 1008 unsigned char buf[DTLS_HMAC_MAX];
ashleymills 0:ff9ebe0cf0e9 1009
ashleymills 0:ff9ebe0cf0e9 1010 if (data_length < DTLS_HS_LENGTH + DTLS_FIN_LENGTH)
ashleymills 0:ff9ebe0cf0e9 1011 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 1012
ashleymills 0:ff9ebe0cf0e9 1013 /* Use a union here to ensure that sufficient stack space is
ashleymills 0:ff9ebe0cf0e9 1014 * reserved. As statebuf and verify_data are not used at the same
ashleymills 0:ff9ebe0cf0e9 1015 * time, we can re-use the storage safely.
ashleymills 0:ff9ebe0cf0e9 1016 */
ashleymills 0:ff9ebe0cf0e9 1017 union {
ashleymills 0:ff9ebe0cf0e9 1018 unsigned char statebuf[DTLS_HASH_CTX_SIZE];
ashleymills 0:ff9ebe0cf0e9 1019 unsigned char verify_data[DTLS_FIN_LENGTH];
ashleymills 0:ff9ebe0cf0e9 1020 } b;
ashleymills 0:ff9ebe0cf0e9 1021
ashleymills 0:ff9ebe0cf0e9 1022 /* temporarily store hash status for roll-back after finalize */
ashleymills 0:ff9ebe0cf0e9 1023 memcpy(b.statebuf, &peer->hs_state.hs_hash, DTLS_HASH_CTX_SIZE);
ashleymills 0:ff9ebe0cf0e9 1024
ashleymills 0:ff9ebe0cf0e9 1025 digest_length = finalize_hs_hash(peer, buf);
ashleymills 0:ff9ebe0cf0e9 1026 /* clear_hash(); */
ashleymills 0:ff9ebe0cf0e9 1027
ashleymills 0:ff9ebe0cf0e9 1028 /* restore hash status */
ashleymills 0:ff9ebe0cf0e9 1029 memcpy(&peer->hs_state.hs_hash, b.statebuf, DTLS_HASH_CTX_SIZE);
ashleymills 0:ff9ebe0cf0e9 1030
ashleymills 0:ff9ebe0cf0e9 1031 if (peer->role == DTLS_CLIENT) {
ashleymills 0:ff9ebe0cf0e9 1032 label = PRF_LABEL(server);
ashleymills 0:ff9ebe0cf0e9 1033 label_size = PRF_LABEL_SIZE(server);
ashleymills 0:ff9ebe0cf0e9 1034 } else { /* client */
ashleymills 0:ff9ebe0cf0e9 1035 label = PRF_LABEL(client);
ashleymills 0:ff9ebe0cf0e9 1036 label_size = PRF_LABEL_SIZE(client);
ashleymills 0:ff9ebe0cf0e9 1037 }
ashleymills 0:ff9ebe0cf0e9 1038
ashleymills 0:ff9ebe0cf0e9 1039 dtls_prf(peer->handshake_params.tmp.master_secret,
ashleymills 0:ff9ebe0cf0e9 1040 DTLS_MASTER_SECRET_LENGTH,
ashleymills 0:ff9ebe0cf0e9 1041 label, label_size,
ashleymills 0:ff9ebe0cf0e9 1042 PRF_LABEL(finished), PRF_LABEL_SIZE(finished),
ashleymills 0:ff9ebe0cf0e9 1043 buf, digest_length,
ashleymills 0:ff9ebe0cf0e9 1044 b.verify_data, sizeof(b.verify_data));
ashleymills 0:ff9ebe0cf0e9 1045
ashleymills 0:ff9ebe0cf0e9 1046 dtls_dsrv_hexdump_log(LOG_DEBUG, "d:", data + DTLS_HS_LENGTH, sizeof(b.verify_data), 0);
ashleymills 0:ff9ebe0cf0e9 1047 dtls_dsrv_hexdump_log(LOG_DEBUG, "v:", b.verify_data, sizeof(b.verify_data), 0);
ashleymills 0:ff9ebe0cf0e9 1048 return memcmp(data + DTLS_HS_LENGTH, b.verify_data, sizeof(b.verify_data));
ashleymills 0:ff9ebe0cf0e9 1049 }
ashleymills 0:ff9ebe0cf0e9 1050
ashleymills 0:ff9ebe0cf0e9 1051 /**
ashleymills 0:ff9ebe0cf0e9 1052 * Prepares the payload given in \p data for sending with
ashleymills 0:ff9ebe0cf0e9 1053 * dtls_send(). The \p data is encrypted and compressed according to
ashleymills 0:ff9ebe0cf0e9 1054 * the current security parameters of \p peer. The result of this
ashleymills 0:ff9ebe0cf0e9 1055 * operation is put into \p sendbuf with a prepended record header of
ashleymills 0:ff9ebe0cf0e9 1056 * type \p type ready for sending. As some cipher suites add a MAC
ashleymills 0:ff9ebe0cf0e9 1057 * before encryption, \p data must be large enough to hold this data
ashleymills 0:ff9ebe0cf0e9 1058 * as well (usually \c dtls_kb_digest_size(CURRENT_CONFIG(peer)).
ashleymills 0:ff9ebe0cf0e9 1059 *
ashleymills 0:ff9ebe0cf0e9 1060 * \param peer The remote peer the packet will be sent to.
ashleymills 0:ff9ebe0cf0e9 1061 * \param type The content type of this record.
ashleymills 0:ff9ebe0cf0e9 1062 * \param data The payload to send.
ashleymills 0:ff9ebe0cf0e9 1063 * \param data_length The size of \p data.
ashleymills 0:ff9ebe0cf0e9 1064 * \param sendbuf The output buffer where the encrypted record
ashleymills 0:ff9ebe0cf0e9 1065 * will be placed.
ashleymills 0:ff9ebe0cf0e9 1066 * \param rlen This parameter must be initialized with the
ashleymills 0:ff9ebe0cf0e9 1067 * maximum size of \p sendbuf and will be updated
ashleymills 0:ff9ebe0cf0e9 1068 * to hold the actual size of the stored packet
ashleymills 0:ff9ebe0cf0e9 1069 * on success. On error, the value of \p rlen is
ashleymills 0:ff9ebe0cf0e9 1070 * undefined.
ashleymills 0:ff9ebe0cf0e9 1071 * \return Less than zero on error, or greater than zero success.
ashleymills 0:ff9ebe0cf0e9 1072 */
ashleymills 0:ff9ebe0cf0e9 1073 static int
ashleymills 0:ff9ebe0cf0e9 1074 dtls_prepare_record(dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 1075 unsigned char type,
ashleymills 0:ff9ebe0cf0e9 1076 uint8 *data_array[], size_t data_len_array[],
ashleymills 0:ff9ebe0cf0e9 1077 size_t data_array_len,
ashleymills 0:ff9ebe0cf0e9 1078 uint8 *sendbuf, size_t *rlen) {
ashleymills 0:ff9ebe0cf0e9 1079 DBG("dtls_prepare_record");
ashleymills 0:ff9ebe0cf0e9 1080
ashleymills 0:ff9ebe0cf0e9 1081 uint8 *p, *start;
ashleymills 0:ff9ebe0cf0e9 1082 int res;
ashleymills 0:ff9ebe0cf0e9 1083 int i;
ashleymills 0:ff9ebe0cf0e9 1084 dtls_security_parameters_t *security = &peer->security_params;
ashleymills 0:ff9ebe0cf0e9 1085
ashleymills 0:ff9ebe0cf0e9 1086 p = dtls_set_record_header(type, peer, sendbuf);
ashleymills 0:ff9ebe0cf0e9 1087 start = p;
ashleymills 0:ff9ebe0cf0e9 1088
ashleymills 0:ff9ebe0cf0e9 1089 if (!peer || security->cipher == TLS_NULL_WITH_NULL_NULL) {
ashleymills 0:ff9ebe0cf0e9 1090 /* no cipher suite */
ashleymills 0:ff9ebe0cf0e9 1091
ashleymills 0:ff9ebe0cf0e9 1092 res = 0;
ashleymills 0:ff9ebe0cf0e9 1093 for (i = 0; i < data_array_len; i++) {
ashleymills 0:ff9ebe0cf0e9 1094 /* check the minimum that we need for packets that are not encrypted */
ashleymills 0:ff9ebe0cf0e9 1095 if (*rlen < (p - start) + data_len_array[i]) {
ashleymills 0:ff9ebe0cf0e9 1096 DBG("dtls_prepare_record: send buffer too small");
ashleymills 0:ff9ebe0cf0e9 1097 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
ashleymills 0:ff9ebe0cf0e9 1098 }
ashleymills 0:ff9ebe0cf0e9 1099
ashleymills 0:ff9ebe0cf0e9 1100 memcpy(p, data_array[i], data_len_array[i]);
ashleymills 0:ff9ebe0cf0e9 1101 p += data_len_array[i];
ashleymills 0:ff9ebe0cf0e9 1102 res += data_len_array[i];
ashleymills 0:ff9ebe0cf0e9 1103 }
ashleymills 0:ff9ebe0cf0e9 1104 } else { /* TLS_PSK_WITH_AES_128_CCM_8 */
ashleymills 0:ff9ebe0cf0e9 1105 dtls_cipher_context_t *cipher_context;
ashleymills 0:ff9ebe0cf0e9 1106
ashleymills 0:ff9ebe0cf0e9 1107 /**
ashleymills 0:ff9ebe0cf0e9 1108 * length of additional_data for the AEAD cipher which consists of
ashleymills 0:ff9ebe0cf0e9 1109 * seq_num(2+6) + type(1) + version(2) + length(2)
ashleymills 0:ff9ebe0cf0e9 1110 */
ashleymills 0:ff9ebe0cf0e9 1111 #define A_DATA_LEN 13
ashleymills 0:ff9ebe0cf0e9 1112 unsigned char nonce[DTLS_CCM_BLOCKSIZE];
ashleymills 0:ff9ebe0cf0e9 1113 unsigned char A_DATA[A_DATA_LEN];
ashleymills 0:ff9ebe0cf0e9 1114
ashleymills 0:ff9ebe0cf0e9 1115 if (security->cipher == TLS_PSK_WITH_AES_128_CCM_8) {
ashleymills 0:ff9ebe0cf0e9 1116 DBG("dtls_prepare_record(): encrypt using TLS_PSK_WITH_AES_128_CCM_8");
ashleymills 0:ff9ebe0cf0e9 1117 } else if (security->cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8) {
ashleymills 0:ff9ebe0cf0e9 1118 DBG("dtls_prepare_record(): encrypt using TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8");
ashleymills 0:ff9ebe0cf0e9 1119 } else {
ashleymills 0:ff9ebe0cf0e9 1120 DBG("dtls_prepare_record(): encrypt using unknown cipher");
ashleymills 0:ff9ebe0cf0e9 1121 }
ashleymills 0:ff9ebe0cf0e9 1122
ashleymills 0:ff9ebe0cf0e9 1123 /* set nonce
ashleymills 0:ff9ebe0cf0e9 1124 from http://tools.ietf.org/html/draft-mcgrew-tls-aes-ccm-03:
ashleymills 0:ff9ebe0cf0e9 1125 struct {
ashleymills 0:ff9ebe0cf0e9 1126 case client:
ashleymills 0:ff9ebe0cf0e9 1127 uint32 client_write_IV; // low order 32-bits
ashleymills 0:ff9ebe0cf0e9 1128 case server:
ashleymills 0:ff9ebe0cf0e9 1129 uint32 server_write_IV; // low order 32-bits
ashleymills 0:ff9ebe0cf0e9 1130 uint64 seq_num;
ashleymills 0:ff9ebe0cf0e9 1131 } CCMNonce.
ashleymills 0:ff9ebe0cf0e9 1132
ashleymills 0:ff9ebe0cf0e9 1133 In DTLS, the 64-bit seq_num is the 16-bit epoch concatenated with the
ashleymills 0:ff9ebe0cf0e9 1134 48-bit seq_num.
ashleymills 0:ff9ebe0cf0e9 1135 */
ashleymills 0:ff9ebe0cf0e9 1136
ashleymills 0:ff9ebe0cf0e9 1137 memcpy(p, &DTLS_RECORD_HEADER(sendbuf)->epoch, 8);
ashleymills 0:ff9ebe0cf0e9 1138 p += 8;
ashleymills 0:ff9ebe0cf0e9 1139 res = 8;
ashleymills 0:ff9ebe0cf0e9 1140
ashleymills 0:ff9ebe0cf0e9 1141 for (i = 0; i < data_array_len; i++) {
ashleymills 0:ff9ebe0cf0e9 1142 /* check the minimum that we need for packets that are not encrypted */
ashleymills 0:ff9ebe0cf0e9 1143 if (*rlen < res + data_len_array[i]) {
ashleymills 0:ff9ebe0cf0e9 1144 DBG("dtls_prepare_record: send buffer too small");
ashleymills 0:ff9ebe0cf0e9 1145 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
ashleymills 0:ff9ebe0cf0e9 1146 }
ashleymills 0:ff9ebe0cf0e9 1147
ashleymills 0:ff9ebe0cf0e9 1148 memcpy(p, data_array[i], data_len_array[i]);
ashleymills 0:ff9ebe0cf0e9 1149 p += data_len_array[i];
ashleymills 0:ff9ebe0cf0e9 1150 res += data_len_array[i];
ashleymills 0:ff9ebe0cf0e9 1151 }
ashleymills 0:ff9ebe0cf0e9 1152
ashleymills 0:ff9ebe0cf0e9 1153 memset(nonce, 0, DTLS_CCM_BLOCKSIZE);
ashleymills 0:ff9ebe0cf0e9 1154 memcpy(nonce, dtls_kb_local_iv(security, peer->role),
ashleymills 0:ff9ebe0cf0e9 1155 dtls_kb_iv_size(security, peer->role));
ashleymills 0:ff9ebe0cf0e9 1156 memcpy(nonce + dtls_kb_iv_size(security, peer->role), start, 8); /* epoch + seq_num */
ashleymills 0:ff9ebe0cf0e9 1157
ashleymills 0:ff9ebe0cf0e9 1158 cipher_context = security->write_cipher;
ashleymills 0:ff9ebe0cf0e9 1159
ashleymills 0:ff9ebe0cf0e9 1160 if (!cipher_context) {
ashleymills 0:ff9ebe0cf0e9 1161 WARN("no write_cipher available!");
ashleymills 0:ff9ebe0cf0e9 1162 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
ashleymills 0:ff9ebe0cf0e9 1163 }
ashleymills 0:ff9ebe0cf0e9 1164
ashleymills 0:ff9ebe0cf0e9 1165 dtls_dsrv_hexdump_log(LOG_DEBUG, "nonce:", nonce, DTLS_CCM_BLOCKSIZE, 0);
ashleymills 0:ff9ebe0cf0e9 1166 dtls_dsrv_hexdump_log(LOG_DEBUG, "key:",
ashleymills 0:ff9ebe0cf0e9 1167 dtls_kb_local_write_key(security, peer->role),
ashleymills 0:ff9ebe0cf0e9 1168 dtls_kb_key_size(security, peer->role), 0);
ashleymills 0:ff9ebe0cf0e9 1169
ashleymills 0:ff9ebe0cf0e9 1170 /* re-use N to create additional data according to RFC 5246, Section 6.2.3.3:
ashleymills 0:ff9ebe0cf0e9 1171 *
ashleymills 0:ff9ebe0cf0e9 1172 * additional_data = seq_num + TLSCompressed.type +
ashleymills 0:ff9ebe0cf0e9 1173 * TLSCompressed.version + TLSCompressed.length;
ashleymills 0:ff9ebe0cf0e9 1174 */
ashleymills 0:ff9ebe0cf0e9 1175 memcpy(A_DATA, &DTLS_RECORD_HEADER(sendbuf)->epoch, 8); /* epoch and seq_num */
ashleymills 0:ff9ebe0cf0e9 1176 memcpy(A_DATA + 8, &DTLS_RECORD_HEADER(sendbuf)->content_type, 3); /* type and version */
ashleymills 0:ff9ebe0cf0e9 1177 dtls_int_to_uint16(A_DATA + 11, res - 8); /* length */
ashleymills 0:ff9ebe0cf0e9 1178
ashleymills 0:ff9ebe0cf0e9 1179 res = dtls_encrypt(cipher_context, start + 8, res - 8, start + 8, nonce,
ashleymills 0:ff9ebe0cf0e9 1180 A_DATA, A_DATA_LEN);
ashleymills 0:ff9ebe0cf0e9 1181
ashleymills 0:ff9ebe0cf0e9 1182 if (res < 0)
ashleymills 0:ff9ebe0cf0e9 1183 return res;
ashleymills 0:ff9ebe0cf0e9 1184
ashleymills 0:ff9ebe0cf0e9 1185 res += 8; /* increment res by size of nonce_explicit */
ashleymills 0:ff9ebe0cf0e9 1186 dtls_dsrv_hexdump_log(LOG_DEBUG, "message:", start, res, 0);
ashleymills 0:ff9ebe0cf0e9 1187 }
ashleymills 0:ff9ebe0cf0e9 1188
ashleymills 0:ff9ebe0cf0e9 1189 /* fix length of fragment in sendbuf */
ashleymills 0:ff9ebe0cf0e9 1190 dtls_int_to_uint16(sendbuf + 11, res);
ashleymills 0:ff9ebe0cf0e9 1191
ashleymills 0:ff9ebe0cf0e9 1192 *rlen = DTLS_RH_LENGTH + res;
ashleymills 0:ff9ebe0cf0e9 1193 return 0;
ashleymills 0:ff9ebe0cf0e9 1194 }
ashleymills 0:ff9ebe0cf0e9 1195
ashleymills 0:ff9ebe0cf0e9 1196 static int
ashleymills 0:ff9ebe0cf0e9 1197 dtls_send_handshake_msg_hash(dtls_context_t *ctx,
ashleymills 0:ff9ebe0cf0e9 1198 dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 1199 session_t *session,
ashleymills 0:ff9ebe0cf0e9 1200 uint8 header_type,
ashleymills 0:ff9ebe0cf0e9 1201 uint8 *data, size_t data_length,
ashleymills 0:ff9ebe0cf0e9 1202 int add_hash)
ashleymills 0:ff9ebe0cf0e9 1203 {
ashleymills 0:ff9ebe0cf0e9 1204 DBG("dtls_send_handshake_msg_hash");
ashleymills 0:ff9ebe0cf0e9 1205 uint8 buf[DTLS_HS_LENGTH];
ashleymills 0:ff9ebe0cf0e9 1206 uint8 *data_array[2];
ashleymills 0:ff9ebe0cf0e9 1207 size_t data_len_array[2];
ashleymills 0:ff9ebe0cf0e9 1208 int i = 0;
ashleymills 0:ff9ebe0cf0e9 1209 uint8 sendbuf[DTLS_MAX_BUF];
ashleymills 0:ff9ebe0cf0e9 1210 size_t len = sizeof(sendbuf);
ashleymills 0:ff9ebe0cf0e9 1211
ashleymills 0:ff9ebe0cf0e9 1212 dtls_set_handshake_header(header_type, (add_hash) ? peer : NULL, data_length, 0,
ashleymills 0:ff9ebe0cf0e9 1213 data_length, buf);
ashleymills 0:ff9ebe0cf0e9 1214
ashleymills 0:ff9ebe0cf0e9 1215 if (add_hash) {
ashleymills 0:ff9ebe0cf0e9 1216 update_hs_hash(peer, buf, sizeof(buf));
ashleymills 0:ff9ebe0cf0e9 1217 }
ashleymills 0:ff9ebe0cf0e9 1218 data_array[i] = buf;
ashleymills 0:ff9ebe0cf0e9 1219 data_len_array[i] = sizeof(buf);
ashleymills 0:ff9ebe0cf0e9 1220 i++;
ashleymills 0:ff9ebe0cf0e9 1221
ashleymills 0:ff9ebe0cf0e9 1222 if (data != NULL) {
ashleymills 0:ff9ebe0cf0e9 1223 if (add_hash) {
ashleymills 0:ff9ebe0cf0e9 1224 update_hs_hash(peer, data, data_length);
ashleymills 0:ff9ebe0cf0e9 1225 }
ashleymills 0:ff9ebe0cf0e9 1226 data_array[i] = data;
ashleymills 0:ff9ebe0cf0e9 1227 data_len_array[i] = data_length;
ashleymills 0:ff9ebe0cf0e9 1228 i++;
ashleymills 0:ff9ebe0cf0e9 1229 }
ashleymills 0:ff9ebe0cf0e9 1230 i = dtls_prepare_record(peer, DTLS_CT_HANDSHAKE, data_array, data_len_array,
ashleymills 0:ff9ebe0cf0e9 1231 i, sendbuf, &len);
ashleymills 0:ff9ebe0cf0e9 1232 if (i < 0) {
ashleymills 0:ff9ebe0cf0e9 1233 return i;
ashleymills 0:ff9ebe0cf0e9 1234 }
ashleymills 0:ff9ebe0cf0e9 1235
ashleymills 0:ff9ebe0cf0e9 1236 return CALL(ctx, write, session, sendbuf, len);
ashleymills 0:ff9ebe0cf0e9 1237 }
ashleymills 0:ff9ebe0cf0e9 1238
ashleymills 0:ff9ebe0cf0e9 1239 static int
ashleymills 0:ff9ebe0cf0e9 1240 dtls_send_handshake_msg(dtls_context_t *ctx,
ashleymills 0:ff9ebe0cf0e9 1241 dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 1242 uint8 header_type,
ashleymills 0:ff9ebe0cf0e9 1243 uint8 *data, size_t data_length)
ashleymills 0:ff9ebe0cf0e9 1244 {
ashleymills 0:ff9ebe0cf0e9 1245 return dtls_send_handshake_msg_hash(ctx, peer, &peer->session,
ashleymills 0:ff9ebe0cf0e9 1246 header_type, data, data_length, 1);
ashleymills 0:ff9ebe0cf0e9 1247 }
ashleymills 0:ff9ebe0cf0e9 1248
ashleymills 0:ff9ebe0cf0e9 1249 /**
ashleymills 0:ff9ebe0cf0e9 1250 * Returns true if the message @p Data is a handshake message that
ashleymills 0:ff9ebe0cf0e9 1251 * must be included in the calculation of verify_data in the Finished
ashleymills 0:ff9ebe0cf0e9 1252 * message.
ashleymills 0:ff9ebe0cf0e9 1253 *
ashleymills 0:ff9ebe0cf0e9 1254 * @param Type The message type. Only handshake messages but the initial
ashleymills 0:ff9ebe0cf0e9 1255 * Client Hello and Hello Verify Request are included in the hash,
ashleymills 0:ff9ebe0cf0e9 1256 * @param Data The PDU to examine.
ashleymills 0:ff9ebe0cf0e9 1257 * @param Length The length of @p Data.
ashleymills 0:ff9ebe0cf0e9 1258 *
ashleymills 0:ff9ebe0cf0e9 1259 * @return @c 1 if @p Data must be included in hash, @c 0 otherwise.
ashleymills 0:ff9ebe0cf0e9 1260 *
ashleymills 0:ff9ebe0cf0e9 1261 * @hideinitializer
ashleymills 0:ff9ebe0cf0e9 1262 */
ashleymills 0:ff9ebe0cf0e9 1263 #define MUST_HASH(Type, Data, Length) \
ashleymills 0:ff9ebe0cf0e9 1264 ((Type) == DTLS_CT_HANDSHAKE && \
ashleymills 0:ff9ebe0cf0e9 1265 ((Data) != NULL) && ((Length) > 0) && \
ashleymills 0:ff9ebe0cf0e9 1266 ((Data)[0] != DTLS_HT_HELLO_VERIFY_REQUEST) && \
ashleymills 0:ff9ebe0cf0e9 1267 ((Data)[0] != DTLS_HT_CLIENT_HELLO || \
ashleymills 0:ff9ebe0cf0e9 1268 ((Length) >= HS_HDR_LENGTH && \
ashleymills 0:ff9ebe0cf0e9 1269 (dtls_uint16_to_int(DTLS_RECORD_HEADER(Data)->epoch > 0) || \
ashleymills 0:ff9ebe0cf0e9 1270 (dtls_uint16_to_int(HANDSHAKE(Data)->message_seq) > 0)))))
ashleymills 0:ff9ebe0cf0e9 1271
ashleymills 0:ff9ebe0cf0e9 1272 /**
ashleymills 0:ff9ebe0cf0e9 1273 * Sends the data passed in @p buf as a DTLS record of type @p type to
ashleymills 0:ff9ebe0cf0e9 1274 * the given peer. The data will be encrypted and compressed according
ashleymills 0:ff9ebe0cf0e9 1275 * to the security parameters for @p peer.
ashleymills 0:ff9ebe0cf0e9 1276 *
ashleymills 0:ff9ebe0cf0e9 1277 * @param ctx The DTLS context in effect.
ashleymills 0:ff9ebe0cf0e9 1278 * @param peer The remote party where the packet is sent.
ashleymills 0:ff9ebe0cf0e9 1279 * @param type The content type of this record.
ashleymills 0:ff9ebe0cf0e9 1280 * @param buf The data to send.
ashleymills 0:ff9ebe0cf0e9 1281 * @param buflen The number of bytes to send from @p buf.
ashleymills 0:ff9ebe0cf0e9 1282 * @return Less than zero in case of an error or the number of
ashleymills 0:ff9ebe0cf0e9 1283 * bytes that have been sent otherwise.
ashleymills 0:ff9ebe0cf0e9 1284 */
ashleymills 0:ff9ebe0cf0e9 1285 static int
ashleymills 0:ff9ebe0cf0e9 1286 dtls_send(dtls_context_t *ctx, dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 1287 unsigned char type,
ashleymills 0:ff9ebe0cf0e9 1288 uint8 *buf, size_t buflen) {
ashleymills 0:ff9ebe0cf0e9 1289
ashleymills 0:ff9ebe0cf0e9 1290 /* We cannot use ctx->sendbuf here as it is reserved for collecting
ashleymills 0:ff9ebe0cf0e9 1291 * the input for this function, i.e. buf == ctx->sendbuf.
ashleymills 0:ff9ebe0cf0e9 1292 *
ashleymills 0:ff9ebe0cf0e9 1293 * TODO: check if we can use the receive buf here. This would mean
ashleymills 0:ff9ebe0cf0e9 1294 * that we might not be able to handle multiple records stuffed in
ashleymills 0:ff9ebe0cf0e9 1295 * one UDP datagram */
ashleymills 0:ff9ebe0cf0e9 1296 unsigned char sendbuf[DTLS_MAX_BUF];
ashleymills 0:ff9ebe0cf0e9 1297 size_t len = sizeof(sendbuf);
ashleymills 0:ff9ebe0cf0e9 1298 int res;
ashleymills 0:ff9ebe0cf0e9 1299
ashleymills 0:ff9ebe0cf0e9 1300 res = dtls_prepare_record(peer, type, &buf, &buflen, 1, sendbuf, &len);
ashleymills 0:ff9ebe0cf0e9 1301
ashleymills 0:ff9ebe0cf0e9 1302 if (res < 0)
ashleymills 0:ff9ebe0cf0e9 1303 return res;
ashleymills 0:ff9ebe0cf0e9 1304
ashleymills 0:ff9ebe0cf0e9 1305 /* if (peer && MUST_HASH(peer, type, buf, buflen)) */
ashleymills 0:ff9ebe0cf0e9 1306 /* update_hs_hash(peer, buf, buflen); */
ashleymills 0:ff9ebe0cf0e9 1307
ashleymills 0:ff9ebe0cf0e9 1308 dtls_dsrv_hexdump_log(LOG_DEBUG, "send header", sendbuf,
ashleymills 0:ff9ebe0cf0e9 1309 sizeof(dtls_record_header_t), 1);
ashleymills 0:ff9ebe0cf0e9 1310 dtls_dsrv_hexdump_log(LOG_DEBUG, "send unencrypted", buf, buflen, 1);
ashleymills 0:ff9ebe0cf0e9 1311
ashleymills 0:ff9ebe0cf0e9 1312 if (type == DTLS_CT_HANDSHAKE && buf[0] != DTLS_HT_HELLO_VERIFY_REQUEST) {
ashleymills 0:ff9ebe0cf0e9 1313 /* copy handshake messages other than HelloVerify into retransmit buffer */
ashleymills 0:ff9ebe0cf0e9 1314 netq_t *n = netq_node_new();
ashleymills 0:ff9ebe0cf0e9 1315 if (n) {
ashleymills 0:ff9ebe0cf0e9 1316 dtls_tick_t now;
ashleymills 0:ff9ebe0cf0e9 1317 dtls_ticks(&now);
ashleymills 0:ff9ebe0cf0e9 1318 n->t = now + 2 * CLOCK_SECOND;
ashleymills 0:ff9ebe0cf0e9 1319 n->retransmit_cnt = 0;
ashleymills 0:ff9ebe0cf0e9 1320 n->timeout = 2 * CLOCK_SECOND;
ashleymills 0:ff9ebe0cf0e9 1321 n->peer = peer;
ashleymills 0:ff9ebe0cf0e9 1322 n->length = buflen;
ashleymills 0:ff9ebe0cf0e9 1323 memcpy(n->data, buf, buflen);
ashleymills 0:ff9ebe0cf0e9 1324
ashleymills 0:ff9ebe0cf0e9 1325 if (!netq_insert_node((netq_t **)ctx->sendqueue, n)) {
ashleymills 0:ff9ebe0cf0e9 1326 WARN("cannot add packet to retransmit buffer");
ashleymills 0:ff9ebe0cf0e9 1327 netq_node_free(n);
ashleymills 0:ff9ebe0cf0e9 1328 #ifdef WITH_CONTIKI
ashleymills 0:ff9ebe0cf0e9 1329 } else {
ashleymills 0:ff9ebe0cf0e9 1330 /* must set timer within the context of the retransmit process */
ashleymills 0:ff9ebe0cf0e9 1331 PROCESS_CONTEXT_BEGIN(&dtls_retransmit_process);
ashleymills 0:ff9ebe0cf0e9 1332 etimer_set(&ctx->retransmit_timer, n->timeout);
ashleymills 0:ff9ebe0cf0e9 1333 PROCESS_CONTEXT_END(&dtls_retransmit_process);
ashleymills 0:ff9ebe0cf0e9 1334 #else /* WITH_CONTIKI */
ashleymills 0:ff9ebe0cf0e9 1335 DBG("copied to sendqueue");
ashleymills 0:ff9ebe0cf0e9 1336 #endif /* WITH_CONTIKI */
ashleymills 0:ff9ebe0cf0e9 1337 }
ashleymills 0:ff9ebe0cf0e9 1338 } else
ashleymills 0:ff9ebe0cf0e9 1339 WARN("retransmit buffer full");
ashleymills 0:ff9ebe0cf0e9 1340 }
ashleymills 0:ff9ebe0cf0e9 1341
ashleymills 0:ff9ebe0cf0e9 1342 /* FIXME: copy to peer's sendqueue (after fragmentation if
ashleymills 0:ff9ebe0cf0e9 1343 * necessary) and initialize retransmit timer */
ashleymills 0:ff9ebe0cf0e9 1344 res = CALL(ctx, write, &peer->session, sendbuf, len);
ashleymills 0:ff9ebe0cf0e9 1345
ashleymills 0:ff9ebe0cf0e9 1346 /* Guess number of bytes application data actually sent:
ashleymills 0:ff9ebe0cf0e9 1347 * dtls_prepare_record() tells us in len the number of bytes to
ashleymills 0:ff9ebe0cf0e9 1348 * send, res will contain the bytes actually sent. */
ashleymills 0:ff9ebe0cf0e9 1349 return res <= 0 ? res : buflen - (len - res);
ashleymills 0:ff9ebe0cf0e9 1350 }
ashleymills 0:ff9ebe0cf0e9 1351
ashleymills 0:ff9ebe0cf0e9 1352 static inline int
ashleymills 0:ff9ebe0cf0e9 1353 dtls_alert(dtls_context_t *ctx, dtls_peer_t *peer, dtls_alert_level_t level,
ashleymills 0:ff9ebe0cf0e9 1354 dtls_alert_t description) {
ashleymills 0:ff9ebe0cf0e9 1355 uint8_t msg[] = { level, description };
ashleymills 0:ff9ebe0cf0e9 1356
ashleymills 0:ff9ebe0cf0e9 1357 dtls_send(ctx, peer, DTLS_CT_ALERT, msg, sizeof(msg));
ashleymills 0:ff9ebe0cf0e9 1358 return 0;
ashleymills 0:ff9ebe0cf0e9 1359 }
ashleymills 0:ff9ebe0cf0e9 1360
ashleymills 0:ff9ebe0cf0e9 1361 int
ashleymills 0:ff9ebe0cf0e9 1362 dtls_close(dtls_context_t *ctx, const session_t *remote) {
ashleymills 0:ff9ebe0cf0e9 1363 int res = -1;
ashleymills 0:ff9ebe0cf0e9 1364 dtls_peer_t *peer;
ashleymills 0:ff9ebe0cf0e9 1365
ashleymills 0:ff9ebe0cf0e9 1366 peer = dtls_get_peer(ctx, remote);
ashleymills 0:ff9ebe0cf0e9 1367
ashleymills 0:ff9ebe0cf0e9 1368 if (peer) {
ashleymills 0:ff9ebe0cf0e9 1369 res = dtls_alert(ctx, peer, DTLS_ALERT_LEVEL_FATAL, DTLS_ALERT_CLOSE_NOTIFY);
ashleymills 0:ff9ebe0cf0e9 1370 /* indicate tear down */
ashleymills 0:ff9ebe0cf0e9 1371 peer->state = DTLS_STATE_CLOSING;
ashleymills 0:ff9ebe0cf0e9 1372 }
ashleymills 0:ff9ebe0cf0e9 1373 return res;
ashleymills 0:ff9ebe0cf0e9 1374 }
ashleymills 0:ff9ebe0cf0e9 1375
ashleymills 0:ff9ebe0cf0e9 1376 static void dtls_destory_peer(dtls_context_t *ctx, dtls_peer_t *peer, int unlink)
ashleymills 0:ff9ebe0cf0e9 1377 {
ashleymills 0:ff9ebe0cf0e9 1378 if (peer->state != DTLS_STATE_CLOSED)
ashleymills 0:ff9ebe0cf0e9 1379 dtls_close(ctx, &peer->session);
ashleymills 0:ff9ebe0cf0e9 1380 if (unlink) {
ashleymills 0:ff9ebe0cf0e9 1381 #ifndef WITH_CONTIKI
ashleymills 0:ff9ebe0cf0e9 1382 HASH_DEL_PEER(ctx->peers, peer);
ashleymills 0:ff9ebe0cf0e9 1383 #else /* WITH_CONTIKI */
ashleymills 0:ff9ebe0cf0e9 1384 list_remove(ctx->peers, peer);
ashleymills 0:ff9ebe0cf0e9 1385
ashleymills 0:ff9ebe0cf0e9 1386 #ifndef NDEBUG
ashleymills 0:ff9ebe0cf0e9 1387 PRINTF("removed peer [");
ashleymills 0:ff9ebe0cf0e9 1388 PRINT6ADDR(&peer->session.addr);
ashleymills 0:ff9ebe0cf0e9 1389 PRINTF("]:%d", uip_ntohs(peer->session.port));
ashleymills 0:ff9ebe0cf0e9 1390 #endif
ashleymills 0:ff9ebe0cf0e9 1391 #endif /* WITH_CONTIKI */
ashleymills 0:ff9ebe0cf0e9 1392 }
ashleymills 0:ff9ebe0cf0e9 1393 dtls_free_peer(peer);
ashleymills 0:ff9ebe0cf0e9 1394 }
ashleymills 0:ff9ebe0cf0e9 1395
ashleymills 0:ff9ebe0cf0e9 1396 /**
ashleymills 0:ff9ebe0cf0e9 1397 * Checks a received Client Hello message for a valid cookie. When the
ashleymills 0:ff9ebe0cf0e9 1398 * Client Hello contains no cookie, the function fails and a Hello
ashleymills 0:ff9ebe0cf0e9 1399 * Verify Request is sent to the peer (using the write callback function
ashleymills 0:ff9ebe0cf0e9 1400 * registered with \p ctx). The return value is \c -1 on error, \c 0 when
ashleymills 0:ff9ebe0cf0e9 1401 * undecided, and \c 1 if the Client Hello was good.
ashleymills 0:ff9ebe0cf0e9 1402 *
ashleymills 0:ff9ebe0cf0e9 1403 * \param ctx The DTLS context.
ashleymills 0:ff9ebe0cf0e9 1404 * \param peer The remote party we are talking to, if any.
ashleymills 0:ff9ebe0cf0e9 1405 * \param session Transport address of the remote peer.
ashleymills 0:ff9ebe0cf0e9 1406 * \param msg The received datagram.
ashleymills 0:ff9ebe0cf0e9 1407 * \param msglen Length of \p msg.
ashleymills 0:ff9ebe0cf0e9 1408 * \return \c 1 if msg is a Client Hello with a valid cookie, \c 0 or
ashleymills 0:ff9ebe0cf0e9 1409 * \c -1 otherwise.
ashleymills 0:ff9ebe0cf0e9 1410 */
ashleymills 0:ff9ebe0cf0e9 1411 static int
ashleymills 0:ff9ebe0cf0e9 1412 dtls_verify_peer(dtls_context_t *ctx,
ashleymills 0:ff9ebe0cf0e9 1413 dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 1414 session_t *session,
ashleymills 0:ff9ebe0cf0e9 1415 uint8 *record,
ashleymills 0:ff9ebe0cf0e9 1416 uint8 *data, size_t data_length)
ashleymills 0:ff9ebe0cf0e9 1417 {
ashleymills 0:ff9ebe0cf0e9 1418
ashleymills 0:ff9ebe0cf0e9 1419 DBG("dtls_verify_peer");
ashleymills 0:ff9ebe0cf0e9 1420
ashleymills 0:ff9ebe0cf0e9 1421 uint8 buf[DTLS_HV_LENGTH + DTLS_COOKIE_LENGTH];
ashleymills 0:ff9ebe0cf0e9 1422 uint8 *p = buf;
ashleymills 0:ff9ebe0cf0e9 1423 int len = DTLS_COOKIE_LENGTH;
ashleymills 0:ff9ebe0cf0e9 1424 uint8 *cookie;
ashleymills 0:ff9ebe0cf0e9 1425 int err;
ashleymills 0:ff9ebe0cf0e9 1426 #undef mycookie
ashleymills 0:ff9ebe0cf0e9 1427 #define mycookie (buf + DTLS_HV_LENGTH)
ashleymills 0:ff9ebe0cf0e9 1428
ashleymills 0:ff9ebe0cf0e9 1429 /* Store cookie where we can reuse it for the HelloVerify request. */
ashleymills 0:ff9ebe0cf0e9 1430 err = dtls_create_cookie(ctx, session, data, data_length, mycookie, &len);
ashleymills 0:ff9ebe0cf0e9 1431 if (err < 0)
ashleymills 0:ff9ebe0cf0e9 1432 return err;
ashleymills 0:ff9ebe0cf0e9 1433
ashleymills 0:ff9ebe0cf0e9 1434 dtls_dsrv_hexdump_log(LOG_DEBUG, "create cookie", mycookie, len, 0);
ashleymills 0:ff9ebe0cf0e9 1435
ashleymills 0:ff9ebe0cf0e9 1436 assert(len == DTLS_COOKIE_LENGTH);
ashleymills 0:ff9ebe0cf0e9 1437
ashleymills 0:ff9ebe0cf0e9 1438 /* Perform cookie check. */
ashleymills 0:ff9ebe0cf0e9 1439 len = dtls_get_cookie(data, data_length, &cookie);
ashleymills 0:ff9ebe0cf0e9 1440 if (len < 0) {
ashleymills 0:ff9ebe0cf0e9 1441 WARN("error while fetching the cookie, err: %i", err);
ashleymills 0:ff9ebe0cf0e9 1442 return err;
ashleymills 0:ff9ebe0cf0e9 1443 }
ashleymills 0:ff9ebe0cf0e9 1444
ashleymills 0:ff9ebe0cf0e9 1445 dtls_dsrv_hexdump_log(LOG_DEBUG, "compare with cookie", cookie, len, 0);
ashleymills 0:ff9ebe0cf0e9 1446
ashleymills 0:ff9ebe0cf0e9 1447 /* check if cookies match */
ashleymills 0:ff9ebe0cf0e9 1448 if (len == DTLS_COOKIE_LENGTH && memcmp(cookie, mycookie, len) == 0) {
ashleymills 0:ff9ebe0cf0e9 1449 DBG("found matching cookie");
ashleymills 0:ff9ebe0cf0e9 1450 return 0;
ashleymills 0:ff9ebe0cf0e9 1451 }
ashleymills 0:ff9ebe0cf0e9 1452
ashleymills 0:ff9ebe0cf0e9 1453 if (len > 0) {
ashleymills 0:ff9ebe0cf0e9 1454 dtls_dsrv_hexdump_log(LOG_DEBUG, "invalid cookie", cookie, len, 0);
ashleymills 0:ff9ebe0cf0e9 1455 } else {
ashleymills 0:ff9ebe0cf0e9 1456 DBG("cookie len is 0!");
ashleymills 0:ff9ebe0cf0e9 1457 }
ashleymills 0:ff9ebe0cf0e9 1458
ashleymills 0:ff9ebe0cf0e9 1459 /* ClientHello did not contain any valid cookie, hence we send a
ashleymills 0:ff9ebe0cf0e9 1460 * HelloVerify request. */
ashleymills 0:ff9ebe0cf0e9 1461
ashleymills 0:ff9ebe0cf0e9 1462 dtls_int_to_uint16(p, DTLS_VERSION);
ashleymills 0:ff9ebe0cf0e9 1463 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 1464
ashleymills 0:ff9ebe0cf0e9 1465 dtls_int_to_uint8(p, DTLS_COOKIE_LENGTH);
ashleymills 0:ff9ebe0cf0e9 1466 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1467
ashleymills 0:ff9ebe0cf0e9 1468 assert(p == mycookie);
ashleymills 0:ff9ebe0cf0e9 1469
ashleymills 0:ff9ebe0cf0e9 1470 p += DTLS_COOKIE_LENGTH;
ashleymills 0:ff9ebe0cf0e9 1471
ashleymills 0:ff9ebe0cf0e9 1472 err = dtls_send_handshake_msg_hash(ctx, peer, session,
ashleymills 0:ff9ebe0cf0e9 1473 DTLS_HT_HELLO_VERIFY_REQUEST,
ashleymills 0:ff9ebe0cf0e9 1474 buf, p - buf, 0);
ashleymills 0:ff9ebe0cf0e9 1475 if (err < 0) {
ashleymills 0:ff9ebe0cf0e9 1476 WARN("cannot send HelloVerify request");
ashleymills 0:ff9ebe0cf0e9 1477 }
ashleymills 0:ff9ebe0cf0e9 1478 return err; /* HelloVerify is sent, now we cannot do anything but wait */
ashleymills 0:ff9ebe0cf0e9 1479
ashleymills 0:ff9ebe0cf0e9 1480 #undef mycookie
ashleymills 0:ff9ebe0cf0e9 1481 }
ashleymills 0:ff9ebe0cf0e9 1482
ashleymills 0:ff9ebe0cf0e9 1483 static int
ashleymills 0:ff9ebe0cf0e9 1484 check_client_certificate_verify(dtls_context_t *ctx,
ashleymills 0:ff9ebe0cf0e9 1485 dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 1486 uint8 *data, size_t data_length)
ashleymills 0:ff9ebe0cf0e9 1487 {
ashleymills 0:ff9ebe0cf0e9 1488 DBG("check_client_certificate_verify");
ashleymills 0:ff9ebe0cf0e9 1489
ashleymills 0:ff9ebe0cf0e9 1490 dtls_handshake_parameters_t *config = &peer->handshake_params;
ashleymills 0:ff9ebe0cf0e9 1491 int i;
ashleymills 0:ff9ebe0cf0e9 1492 unsigned char *result_r;
ashleymills 0:ff9ebe0cf0e9 1493 unsigned char *result_s;
ashleymills 0:ff9ebe0cf0e9 1494 dtls_hash_ctx hs_hash;
ashleymills 0:ff9ebe0cf0e9 1495 unsigned char sha256hash[DTLS_HMAC_DIGEST_SIZE];
ashleymills 0:ff9ebe0cf0e9 1496
ashleymills 0:ff9ebe0cf0e9 1497 assert(config->cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
ashleymills 0:ff9ebe0cf0e9 1498
ashleymills 0:ff9ebe0cf0e9 1499 data += DTLS_HS_LENGTH;
ashleymills 0:ff9ebe0cf0e9 1500
ashleymills 0:ff9ebe0cf0e9 1501 if (data_length < DTLS_HS_LENGTH + DTLS_CV_LENGTH) {
ashleymills 0:ff9ebe0cf0e9 1502 DBG("the package length does not match the expected");
ashleymills 0:ff9ebe0cf0e9 1503 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 1504 }
ashleymills 0:ff9ebe0cf0e9 1505
ashleymills 0:ff9ebe0cf0e9 1506 if (dtls_uint8_to_int(data) != TLS_EXT_SIG_HASH_ALGO_SHA256) {
ashleymills 0:ff9ebe0cf0e9 1507 DBG("only sha256 is supported in certificate verify");
ashleymills 0:ff9ebe0cf0e9 1508 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 1509 }
ashleymills 0:ff9ebe0cf0e9 1510 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1511 data_length -= sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1512
ashleymills 0:ff9ebe0cf0e9 1513 if (dtls_uint8_to_int(data) != TLS_EXT_SIG_HASH_ALGO_ECDSA) {
ashleymills 0:ff9ebe0cf0e9 1514 DBG("only ecdsa signature is supported in client verify");
ashleymills 0:ff9ebe0cf0e9 1515 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 1516 }
ashleymills 0:ff9ebe0cf0e9 1517 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1518 data_length -= sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1519
ashleymills 0:ff9ebe0cf0e9 1520 if (data_length < dtls_uint16_to_int(data)) {
ashleymills 0:ff9ebe0cf0e9 1521 DBG("signature length wrong");
ashleymills 0:ff9ebe0cf0e9 1522 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 1523 }
ashleymills 0:ff9ebe0cf0e9 1524 data += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 1525 data_length -= sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 1526
ashleymills 0:ff9ebe0cf0e9 1527 if (dtls_uint8_to_int(data) != 0x30) {
ashleymills 0:ff9ebe0cf0e9 1528 DBG("wrong ASN.1 struct, expected SEQUENCE");
ashleymills 0:ff9ebe0cf0e9 1529 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 1530 }
ashleymills 0:ff9ebe0cf0e9 1531 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1532 data_length -= sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1533
ashleymills 0:ff9ebe0cf0e9 1534 if (data_length < dtls_uint8_to_int(data)) {
ashleymills 0:ff9ebe0cf0e9 1535 DBG("signature length wrong");
ashleymills 0:ff9ebe0cf0e9 1536 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 1537 }
ashleymills 0:ff9ebe0cf0e9 1538 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1539 data_length -= sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1540
ashleymills 0:ff9ebe0cf0e9 1541 if (dtls_uint8_to_int(data) != 0x02) {
ashleymills 0:ff9ebe0cf0e9 1542 DBG("wrong ASN.1 struct, expected Integer");
ashleymills 0:ff9ebe0cf0e9 1543 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 1544 }
ashleymills 0:ff9ebe0cf0e9 1545 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1546 data_length -= sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1547
ashleymills 0:ff9ebe0cf0e9 1548 i = dtls_uint8_to_int(data);
ashleymills 0:ff9ebe0cf0e9 1549 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1550 data_length -= sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1551
ashleymills 0:ff9ebe0cf0e9 1552 /* Sometimes these values have a leeding 0 byte */
ashleymills 0:ff9ebe0cf0e9 1553 result_r = data + i - DTLS_EC_KEY_SIZE;
ashleymills 0:ff9ebe0cf0e9 1554
ashleymills 0:ff9ebe0cf0e9 1555 data += i;
ashleymills 0:ff9ebe0cf0e9 1556 data_length -= i;
ashleymills 0:ff9ebe0cf0e9 1557
ashleymills 0:ff9ebe0cf0e9 1558 if (dtls_uint8_to_int(data) != 0x02) {
ashleymills 0:ff9ebe0cf0e9 1559 DBG("wrong ASN.1 struct, expected Integer");
ashleymills 0:ff9ebe0cf0e9 1560 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 1561 }
ashleymills 0:ff9ebe0cf0e9 1562 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1563 data_length -= sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1564
ashleymills 0:ff9ebe0cf0e9 1565 i = dtls_uint8_to_int(data);
ashleymills 0:ff9ebe0cf0e9 1566 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1567 data_length -= sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1568
ashleymills 0:ff9ebe0cf0e9 1569 /* Sometimes these values have a leeding 0 byte */
ashleymills 0:ff9ebe0cf0e9 1570 result_s = data + i - DTLS_EC_KEY_SIZE;
ashleymills 0:ff9ebe0cf0e9 1571
ashleymills 0:ff9ebe0cf0e9 1572 data += i;
ashleymills 0:ff9ebe0cf0e9 1573 data_length -= i;
ashleymills 0:ff9ebe0cf0e9 1574
ashleymills 0:ff9ebe0cf0e9 1575 copy_hs_hash(peer, &hs_hash);
ashleymills 0:ff9ebe0cf0e9 1576
ashleymills 0:ff9ebe0cf0e9 1577 dtls_hash_finalize(sha256hash, &hs_hash);
ashleymills 0:ff9ebe0cf0e9 1578
ashleymills 0:ff9ebe0cf0e9 1579 i = dtls_ecdsa_verify_sig_hash(config->keyx.ecdsa.other_pub_x, config->keyx.ecdsa.other_pub_y,
ashleymills 0:ff9ebe0cf0e9 1580 sizeof(config->keyx.ecdsa.other_pub_x),
ashleymills 0:ff9ebe0cf0e9 1581 sha256hash, sizeof(sha256hash),
ashleymills 0:ff9ebe0cf0e9 1582 result_r, result_s);
ashleymills 0:ff9ebe0cf0e9 1583
ashleymills 0:ff9ebe0cf0e9 1584 if (i < 0) {
ashleymills 0:ff9ebe0cf0e9 1585 DBG("wrong signature err: %i", i);
ashleymills 0:ff9ebe0cf0e9 1586 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 1587 }
ashleymills 0:ff9ebe0cf0e9 1588 return 0;
ashleymills 0:ff9ebe0cf0e9 1589 }
ashleymills 0:ff9ebe0cf0e9 1590
ashleymills 0:ff9ebe0cf0e9 1591 static int
ashleymills 0:ff9ebe0cf0e9 1592 dtls_send_server_hello(dtls_context_t *ctx, dtls_peer_t *peer)
ashleymills 0:ff9ebe0cf0e9 1593 {
ashleymills 0:ff9ebe0cf0e9 1594 /* Ensure that the largest message to create fits in our source
ashleymills 0:ff9ebe0cf0e9 1595 * buffer. (The size of the destination buffer is checked by the
ashleymills 0:ff9ebe0cf0e9 1596 * encoding function, so we do not need to guess.) */
ashleymills 0:ff9ebe0cf0e9 1597 uint8 buf[DTLS_SH_LENGTH + 2 + 5 + 5 + 8 + 6];
ashleymills 0:ff9ebe0cf0e9 1598 uint8 *p;
ashleymills 0:ff9ebe0cf0e9 1599 int ecdsa;
ashleymills 0:ff9ebe0cf0e9 1600 uint8 extension_size;
ashleymills 0:ff9ebe0cf0e9 1601 dtls_handshake_parameters_t *handshake = &peer->handshake_params;
ashleymills 0:ff9ebe0cf0e9 1602 dtls_tick_t now;
ashleymills 0:ff9ebe0cf0e9 1603
ashleymills 0:ff9ebe0cf0e9 1604 ecdsa = handshake->cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8;
ashleymills 0:ff9ebe0cf0e9 1605
ashleymills 0:ff9ebe0cf0e9 1606 extension_size = (ecdsa) ? 2 + 5 + 5 + 8 + 6 : 0;
ashleymills 0:ff9ebe0cf0e9 1607
ashleymills 0:ff9ebe0cf0e9 1608 /* Handshake header */
ashleymills 0:ff9ebe0cf0e9 1609 p = buf;
ashleymills 0:ff9ebe0cf0e9 1610
ashleymills 0:ff9ebe0cf0e9 1611 /* ServerHello */
ashleymills 0:ff9ebe0cf0e9 1612 dtls_int_to_uint16(p, DTLS_VERSION);
ashleymills 0:ff9ebe0cf0e9 1613 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 1614
ashleymills 0:ff9ebe0cf0e9 1615 /* Set server random: First 4 bytes are the server's Unix timestamp,
ashleymills 0:ff9ebe0cf0e9 1616 * followed by 28 bytes of generate random data. */
ashleymills 0:ff9ebe0cf0e9 1617 dtls_ticks(&now);
ashleymills 0:ff9ebe0cf0e9 1618 dtls_int_to_uint32(handshake->tmp.random.server, now / CLOCK_SECOND);
ashleymills 0:ff9ebe0cf0e9 1619 prng(handshake->tmp.random.server + 4, 28);
ashleymills 0:ff9ebe0cf0e9 1620
ashleymills 0:ff9ebe0cf0e9 1621 memcpy(p, handshake->tmp.random.server, DTLS_RANDOM_LENGTH);
ashleymills 0:ff9ebe0cf0e9 1622 p += DTLS_RANDOM_LENGTH;
ashleymills 0:ff9ebe0cf0e9 1623
ashleymills 0:ff9ebe0cf0e9 1624 *p++ = 0; /* no session id */
ashleymills 0:ff9ebe0cf0e9 1625
ashleymills 0:ff9ebe0cf0e9 1626 if (handshake->cipher != TLS_NULL_WITH_NULL_NULL) {
ashleymills 0:ff9ebe0cf0e9 1627 /* selected cipher suite */
ashleymills 0:ff9ebe0cf0e9 1628 dtls_int_to_uint16(p, handshake->cipher);
ashleymills 0:ff9ebe0cf0e9 1629 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 1630
ashleymills 0:ff9ebe0cf0e9 1631 /* selected compression method */
ashleymills 0:ff9ebe0cf0e9 1632 if (handshake->compression >= 0)
ashleymills 0:ff9ebe0cf0e9 1633 *p++ = compression_methods[handshake->compression];
ashleymills 0:ff9ebe0cf0e9 1634 }
ashleymills 0:ff9ebe0cf0e9 1635
ashleymills 0:ff9ebe0cf0e9 1636 if (extension_size) {
ashleymills 0:ff9ebe0cf0e9 1637 /* length of the extensions */
ashleymills 0:ff9ebe0cf0e9 1638 dtls_int_to_uint16(p, extension_size - 2);
ashleymills 0:ff9ebe0cf0e9 1639 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 1640 }
ashleymills 0:ff9ebe0cf0e9 1641
ashleymills 0:ff9ebe0cf0e9 1642 if (ecdsa) {
ashleymills 0:ff9ebe0cf0e9 1643 /* client certificate type extension */
ashleymills 0:ff9ebe0cf0e9 1644 dtls_int_to_uint16(p, TLS_EXT_CLIENT_CERIFICATE_TYPE);
ashleymills 0:ff9ebe0cf0e9 1645 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 1646
ashleymills 0:ff9ebe0cf0e9 1647 /* length of this extension type */
ashleymills 0:ff9ebe0cf0e9 1648 dtls_int_to_uint16(p, 1);
ashleymills 0:ff9ebe0cf0e9 1649 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 1650
ashleymills 0:ff9ebe0cf0e9 1651 dtls_int_to_uint8(p, TLS_CERT_TYPE_OOB);
ashleymills 0:ff9ebe0cf0e9 1652 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1653
ashleymills 0:ff9ebe0cf0e9 1654 /* client certificate type extension */
ashleymills 0:ff9ebe0cf0e9 1655 dtls_int_to_uint16(p, TLS_EXT_SERVER_CERIFICATE_TYPE);
ashleymills 0:ff9ebe0cf0e9 1656 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 1657
ashleymills 0:ff9ebe0cf0e9 1658 /* length of this extension type */
ashleymills 0:ff9ebe0cf0e9 1659 dtls_int_to_uint16(p, 1);
ashleymills 0:ff9ebe0cf0e9 1660 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 1661
ashleymills 0:ff9ebe0cf0e9 1662 dtls_int_to_uint8(p, TLS_CERT_TYPE_OOB);
ashleymills 0:ff9ebe0cf0e9 1663 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1664
ashleymills 0:ff9ebe0cf0e9 1665 /* elliptic_curves */
ashleymills 0:ff9ebe0cf0e9 1666 dtls_int_to_uint16(p, TLS_EXT_ELLIPTIC_CURVES);
ashleymills 0:ff9ebe0cf0e9 1667 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 1668
ashleymills 0:ff9ebe0cf0e9 1669 /* length of this extension type */
ashleymills 0:ff9ebe0cf0e9 1670 dtls_int_to_uint16(p, 4);
ashleymills 0:ff9ebe0cf0e9 1671 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 1672
ashleymills 0:ff9ebe0cf0e9 1673 /* length of the list */
ashleymills 0:ff9ebe0cf0e9 1674 dtls_int_to_uint16(p, 2);
ashleymills 0:ff9ebe0cf0e9 1675 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 1676
ashleymills 0:ff9ebe0cf0e9 1677 dtls_int_to_uint16(p, TLS_EXT_ELLIPTIC_CURVES_SECP256R1);
ashleymills 0:ff9ebe0cf0e9 1678 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 1679
ashleymills 0:ff9ebe0cf0e9 1680 /* ec_point_formats */
ashleymills 0:ff9ebe0cf0e9 1681 dtls_int_to_uint16(p, TLS_EXT_EC_POINT_FORMATS);
ashleymills 0:ff9ebe0cf0e9 1682 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 1683
ashleymills 0:ff9ebe0cf0e9 1684 /* length of this extension type */
ashleymills 0:ff9ebe0cf0e9 1685 dtls_int_to_uint16(p, 2);
ashleymills 0:ff9ebe0cf0e9 1686 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 1687
ashleymills 0:ff9ebe0cf0e9 1688 /* number of supported formats */
ashleymills 0:ff9ebe0cf0e9 1689 dtls_int_to_uint8(p, 1);
ashleymills 0:ff9ebe0cf0e9 1690 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1691
ashleymills 0:ff9ebe0cf0e9 1692 dtls_int_to_uint8(p, TLS_EXT_EC_POINT_FORMATS_UNCOMPRESSED);
ashleymills 0:ff9ebe0cf0e9 1693 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1694 }
ashleymills 0:ff9ebe0cf0e9 1695
ashleymills 0:ff9ebe0cf0e9 1696 assert(p - buf <= sizeof(buf));
ashleymills 0:ff9ebe0cf0e9 1697
ashleymills 0:ff9ebe0cf0e9 1698 return dtls_send_handshake_msg(ctx, peer, DTLS_HT_SERVER_HELLO,
ashleymills 0:ff9ebe0cf0e9 1699 buf, p - buf);
ashleymills 0:ff9ebe0cf0e9 1700 }
ashleymills 0:ff9ebe0cf0e9 1701
ashleymills 0:ff9ebe0cf0e9 1702 static int
ashleymills 0:ff9ebe0cf0e9 1703 dtls_send_certificate_ecdsa(dtls_context_t *ctx, dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 1704 const dtls_ecdsa_key_t *key)
ashleymills 0:ff9ebe0cf0e9 1705 {
ashleymills 0:ff9ebe0cf0e9 1706 DBG("dtls_send_certificate_ecdsa");
ashleymills 0:ff9ebe0cf0e9 1707 uint8 buf[DTLS_CE_LENGTH];
ashleymills 0:ff9ebe0cf0e9 1708 uint8 *p;
ashleymills 0:ff9ebe0cf0e9 1709
ashleymills 0:ff9ebe0cf0e9 1710 /* Certificate
ashleymills 0:ff9ebe0cf0e9 1711 *
ashleymills 0:ff9ebe0cf0e9 1712 * Start message construction at beginning of buffer. */
ashleymills 0:ff9ebe0cf0e9 1713 p = buf;
ashleymills 0:ff9ebe0cf0e9 1714
ashleymills 0:ff9ebe0cf0e9 1715 dtls_int_to_uint24(p, 94);
ashleymills 0:ff9ebe0cf0e9 1716 p += sizeof(uint24);
ashleymills 0:ff9ebe0cf0e9 1717
ashleymills 0:ff9ebe0cf0e9 1718 dtls_int_to_uint24(p, 91);
ashleymills 0:ff9ebe0cf0e9 1719 p += sizeof(uint24);
ashleymills 0:ff9ebe0cf0e9 1720
ashleymills 0:ff9ebe0cf0e9 1721 memcpy(p, &cert_asn1_header, sizeof(cert_asn1_header));
ashleymills 0:ff9ebe0cf0e9 1722 p += sizeof(cert_asn1_header);
ashleymills 0:ff9ebe0cf0e9 1723
ashleymills 0:ff9ebe0cf0e9 1724 memcpy(p, key->pub_key_x, DTLS_EC_KEY_SIZE);
ashleymills 0:ff9ebe0cf0e9 1725 p += DTLS_EC_KEY_SIZE;
ashleymills 0:ff9ebe0cf0e9 1726
ashleymills 0:ff9ebe0cf0e9 1727 memcpy(p, key->pub_key_y, DTLS_EC_KEY_SIZE);
ashleymills 0:ff9ebe0cf0e9 1728 p += DTLS_EC_KEY_SIZE;
ashleymills 0:ff9ebe0cf0e9 1729
ashleymills 0:ff9ebe0cf0e9 1730 assert(p - buf <= sizeof(buf));
ashleymills 0:ff9ebe0cf0e9 1731
ashleymills 0:ff9ebe0cf0e9 1732 return dtls_send_handshake_msg(ctx, peer, DTLS_HT_CERTIFICATE,
ashleymills 0:ff9ebe0cf0e9 1733 buf, p - buf);
ashleymills 0:ff9ebe0cf0e9 1734 }
ashleymills 0:ff9ebe0cf0e9 1735
ashleymills 0:ff9ebe0cf0e9 1736 static uint8 *
ashleymills 0:ff9ebe0cf0e9 1737 dtls_add_ecdsa_signature_elem(uint8 *p, uint32_t *point_r, uint32_t *point_s)
ashleymills 0:ff9ebe0cf0e9 1738 {
ashleymills 0:ff9ebe0cf0e9 1739 int len_r;
ashleymills 0:ff9ebe0cf0e9 1740 int len_s;
ashleymills 0:ff9ebe0cf0e9 1741
ashleymills 0:ff9ebe0cf0e9 1742 #define R_KEY_OFFSET (2 + 1 + 1 + 1 + 1)
ashleymills 0:ff9ebe0cf0e9 1743 #define S_KEY_OFFSET(len_s) (R_KEY_OFFSET + (len_s) + 1 + 1)
ashleymills 0:ff9ebe0cf0e9 1744 /* store the pointer to the r component of the signature and make space */
ashleymills 0:ff9ebe0cf0e9 1745 len_r = dtls_ec_key_from_uint32_asn1(point_r, DTLS_EC_KEY_SIZE, p + R_KEY_OFFSET);
ashleymills 0:ff9ebe0cf0e9 1746 len_s = dtls_ec_key_from_uint32_asn1(point_s, DTLS_EC_KEY_SIZE, p + S_KEY_OFFSET(len_r));
ashleymills 0:ff9ebe0cf0e9 1747
ashleymills 0:ff9ebe0cf0e9 1748 #undef R_KEY_OFFSET
ashleymills 0:ff9ebe0cf0e9 1749 #undef S_KEY_OFFSET
ashleymills 0:ff9ebe0cf0e9 1750
ashleymills 0:ff9ebe0cf0e9 1751 /* length of signature */
ashleymills 0:ff9ebe0cf0e9 1752 dtls_int_to_uint16(p, len_r + len_s + 2 + 2 + 2);
ashleymills 0:ff9ebe0cf0e9 1753 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 1754
ashleymills 0:ff9ebe0cf0e9 1755 /* ASN.1 SEQUENCE */
ashleymills 0:ff9ebe0cf0e9 1756 dtls_int_to_uint8(p, 0x30);
ashleymills 0:ff9ebe0cf0e9 1757 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1758
ashleymills 0:ff9ebe0cf0e9 1759 dtls_int_to_uint8(p, len_r + len_s + 2 + 2);
ashleymills 0:ff9ebe0cf0e9 1760 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1761
ashleymills 0:ff9ebe0cf0e9 1762 /* ASN.1 Integer r */
ashleymills 0:ff9ebe0cf0e9 1763 dtls_int_to_uint8(p, 0x02);
ashleymills 0:ff9ebe0cf0e9 1764 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1765
ashleymills 0:ff9ebe0cf0e9 1766 dtls_int_to_uint8(p, len_r);
ashleymills 0:ff9ebe0cf0e9 1767 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1768
ashleymills 0:ff9ebe0cf0e9 1769 /* the pint r was added here */
ashleymills 0:ff9ebe0cf0e9 1770 p += len_r;
ashleymills 0:ff9ebe0cf0e9 1771
ashleymills 0:ff9ebe0cf0e9 1772 /* ASN.1 Integer s */
ashleymills 0:ff9ebe0cf0e9 1773 dtls_int_to_uint8(p, 0x02);
ashleymills 0:ff9ebe0cf0e9 1774 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1775
ashleymills 0:ff9ebe0cf0e9 1776 dtls_int_to_uint8(p, len_s);
ashleymills 0:ff9ebe0cf0e9 1777 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1778
ashleymills 0:ff9ebe0cf0e9 1779 /* the pint s was added here */
ashleymills 0:ff9ebe0cf0e9 1780 p += len_s;
ashleymills 0:ff9ebe0cf0e9 1781
ashleymills 0:ff9ebe0cf0e9 1782 return p;
ashleymills 0:ff9ebe0cf0e9 1783 }
ashleymills 0:ff9ebe0cf0e9 1784
ashleymills 0:ff9ebe0cf0e9 1785 static int
ashleymills 0:ff9ebe0cf0e9 1786 dtls_send_server_key_exchange_ecdh(dtls_context_t *ctx, dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 1787 const dtls_ecdsa_key_t *key)
ashleymills 0:ff9ebe0cf0e9 1788 {
ashleymills 0:ff9ebe0cf0e9 1789 /* The ASN.1 Integer representation of an 32 byte unsigned int could be
ashleymills 0:ff9ebe0cf0e9 1790 * 33 bytes long add space for that */
ashleymills 0:ff9ebe0cf0e9 1791 uint8 buf[DTLS_SKEXEC_LENGTH + 2];
ashleymills 0:ff9ebe0cf0e9 1792 uint8 *p;
ashleymills 0:ff9ebe0cf0e9 1793 uint8 *key_params;
ashleymills 0:ff9ebe0cf0e9 1794 uint8 *ephemeral_pub_x;
ashleymills 0:ff9ebe0cf0e9 1795 uint8 *ephemeral_pub_y;
ashleymills 0:ff9ebe0cf0e9 1796 uint32_t point_r[9];
ashleymills 0:ff9ebe0cf0e9 1797 uint32_t point_s[9];
ashleymills 0:ff9ebe0cf0e9 1798 dtls_handshake_parameters_t *config = &peer->handshake_params;
ashleymills 0:ff9ebe0cf0e9 1799
ashleymills 0:ff9ebe0cf0e9 1800 /* ServerKeyExchange
ashleymills 0:ff9ebe0cf0e9 1801 *
ashleymills 0:ff9ebe0cf0e9 1802 * Start message construction at beginning of buffer. */
ashleymills 0:ff9ebe0cf0e9 1803 p = buf;
ashleymills 0:ff9ebe0cf0e9 1804
ashleymills 0:ff9ebe0cf0e9 1805 key_params = p;
ashleymills 0:ff9ebe0cf0e9 1806 /* ECCurveType curve_type: named_curve */
ashleymills 0:ff9ebe0cf0e9 1807 dtls_int_to_uint8(p, 3);
ashleymills 0:ff9ebe0cf0e9 1808 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1809
ashleymills 0:ff9ebe0cf0e9 1810 /* NamedCurve namedcurve: secp256r1 */
ashleymills 0:ff9ebe0cf0e9 1811 dtls_int_to_uint16(p, 23);
ashleymills 0:ff9ebe0cf0e9 1812 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 1813
ashleymills 0:ff9ebe0cf0e9 1814 dtls_int_to_uint8(p, 1 + 2 * DTLS_EC_KEY_SIZE);
ashleymills 0:ff9ebe0cf0e9 1815 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1816
ashleymills 0:ff9ebe0cf0e9 1817 /* This should be an uncompressed point, but I do not have access to the sepc. */
ashleymills 0:ff9ebe0cf0e9 1818 dtls_int_to_uint8(p, 4);
ashleymills 0:ff9ebe0cf0e9 1819 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1820
ashleymills 0:ff9ebe0cf0e9 1821 /* store the pointer to the x component of the pub key and make space */
ashleymills 0:ff9ebe0cf0e9 1822 ephemeral_pub_x = p;
ashleymills 0:ff9ebe0cf0e9 1823 p += DTLS_EC_KEY_SIZE;
ashleymills 0:ff9ebe0cf0e9 1824
ashleymills 0:ff9ebe0cf0e9 1825 /* store the pointer to the y component of the pub key and make space */
ashleymills 0:ff9ebe0cf0e9 1826 ephemeral_pub_y = p;
ashleymills 0:ff9ebe0cf0e9 1827 p += DTLS_EC_KEY_SIZE;
ashleymills 0:ff9ebe0cf0e9 1828
ashleymills 0:ff9ebe0cf0e9 1829 dtls_ecdsa_generate_key(config->keyx.ecdsa.own_eph_priv,
ashleymills 0:ff9ebe0cf0e9 1830 ephemeral_pub_x, ephemeral_pub_y,
ashleymills 0:ff9ebe0cf0e9 1831 DTLS_EC_KEY_SIZE);
ashleymills 0:ff9ebe0cf0e9 1832
ashleymills 0:ff9ebe0cf0e9 1833 /* sign the ephemeral and its paramaters */
ashleymills 0:ff9ebe0cf0e9 1834 dtls_ecdsa_create_sig(key->priv_key, DTLS_EC_KEY_SIZE,
ashleymills 0:ff9ebe0cf0e9 1835 config->tmp.random.client, DTLS_RANDOM_LENGTH,
ashleymills 0:ff9ebe0cf0e9 1836 config->tmp.random.server, DTLS_RANDOM_LENGTH,
ashleymills 0:ff9ebe0cf0e9 1837 key_params, p - key_params,
ashleymills 0:ff9ebe0cf0e9 1838 point_r, point_s);
ashleymills 0:ff9ebe0cf0e9 1839
ashleymills 0:ff9ebe0cf0e9 1840 p = dtls_add_ecdsa_signature_elem(p, point_r, point_s);
ashleymills 0:ff9ebe0cf0e9 1841
ashleymills 0:ff9ebe0cf0e9 1842 assert(p - buf <= sizeof(buf));
ashleymills 0:ff9ebe0cf0e9 1843
ashleymills 0:ff9ebe0cf0e9 1844 return dtls_send_handshake_msg(ctx, peer, DTLS_HT_SERVER_KEY_EXCHANGE,
ashleymills 0:ff9ebe0cf0e9 1845 buf, p - buf);
ashleymills 0:ff9ebe0cf0e9 1846 }
ashleymills 0:ff9ebe0cf0e9 1847
ashleymills 0:ff9ebe0cf0e9 1848 static int
ashleymills 0:ff9ebe0cf0e9 1849 dtls_send_server_key_exchange_psk(dtls_context_t *ctx, dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 1850 const dtls_psk_key_t *key)
ashleymills 0:ff9ebe0cf0e9 1851 {
ashleymills 0:ff9ebe0cf0e9 1852 uint8 buf[DTLS_SKEXECPSK_LENGTH_MAX];
ashleymills 0:ff9ebe0cf0e9 1853 uint8 *p;
ashleymills 0:ff9ebe0cf0e9 1854
ashleymills 0:ff9ebe0cf0e9 1855 p = buf;
ashleymills 0:ff9ebe0cf0e9 1856
ashleymills 0:ff9ebe0cf0e9 1857 if (key->id_length > DTLS_PSK_MAX_CLIENT_IDENTITY_LEN) {
ashleymills 0:ff9ebe0cf0e9 1858 WARN("psk identity hint is too long");
ashleymills 0:ff9ebe0cf0e9 1859 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
ashleymills 0:ff9ebe0cf0e9 1860 }
ashleymills 0:ff9ebe0cf0e9 1861
ashleymills 0:ff9ebe0cf0e9 1862 dtls_int_to_uint16(p, key->id_length);
ashleymills 0:ff9ebe0cf0e9 1863 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 1864
ashleymills 0:ff9ebe0cf0e9 1865 memcpy(p, key->id, key->id_length);
ashleymills 0:ff9ebe0cf0e9 1866 p += key->id_length;
ashleymills 0:ff9ebe0cf0e9 1867
ashleymills 0:ff9ebe0cf0e9 1868 assert(p - buf <= sizeof(buf));
ashleymills 0:ff9ebe0cf0e9 1869
ashleymills 0:ff9ebe0cf0e9 1870 return dtls_send_handshake_msg(ctx, peer, DTLS_HT_SERVER_KEY_EXCHANGE,
ashleymills 0:ff9ebe0cf0e9 1871 buf, p - buf);
ashleymills 0:ff9ebe0cf0e9 1872 }
ashleymills 0:ff9ebe0cf0e9 1873
ashleymills 0:ff9ebe0cf0e9 1874 static int
ashleymills 0:ff9ebe0cf0e9 1875 dtls_send_server_certificate_request(dtls_context_t *ctx, dtls_peer_t *peer)
ashleymills 0:ff9ebe0cf0e9 1876 {
ashleymills 0:ff9ebe0cf0e9 1877 uint8 buf[8];
ashleymills 0:ff9ebe0cf0e9 1878 uint8 *p;
ashleymills 0:ff9ebe0cf0e9 1879
ashleymills 0:ff9ebe0cf0e9 1880 /* ServerHelloDone
ashleymills 0:ff9ebe0cf0e9 1881 *
ashleymills 0:ff9ebe0cf0e9 1882 * Start message construction at beginning of buffer. */
ashleymills 0:ff9ebe0cf0e9 1883 p = buf;
ashleymills 0:ff9ebe0cf0e9 1884
ashleymills 0:ff9ebe0cf0e9 1885 /* certificate_types */
ashleymills 0:ff9ebe0cf0e9 1886 dtls_int_to_uint8(p, 1);
ashleymills 0:ff9ebe0cf0e9 1887 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1888
ashleymills 0:ff9ebe0cf0e9 1889 /* ecdsa_sign */
ashleymills 0:ff9ebe0cf0e9 1890 dtls_int_to_uint8(p, 64);
ashleymills 0:ff9ebe0cf0e9 1891 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1892
ashleymills 0:ff9ebe0cf0e9 1893 /* supported_signature_algorithms */
ashleymills 0:ff9ebe0cf0e9 1894 dtls_int_to_uint16(p, 2);
ashleymills 0:ff9ebe0cf0e9 1895 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 1896
ashleymills 0:ff9ebe0cf0e9 1897 /* sha256 */
ashleymills 0:ff9ebe0cf0e9 1898 dtls_int_to_uint8(p, TLS_EXT_SIG_HASH_ALGO_SHA256);
ashleymills 0:ff9ebe0cf0e9 1899 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1900
ashleymills 0:ff9ebe0cf0e9 1901 /* ecdsa */
ashleymills 0:ff9ebe0cf0e9 1902 dtls_int_to_uint8(p, TLS_EXT_SIG_HASH_ALGO_ECDSA);
ashleymills 0:ff9ebe0cf0e9 1903 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 1904
ashleymills 0:ff9ebe0cf0e9 1905 /* certificate_authoritiess */
ashleymills 0:ff9ebe0cf0e9 1906 dtls_int_to_uint16(p, 0);
ashleymills 0:ff9ebe0cf0e9 1907 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 1908
ashleymills 0:ff9ebe0cf0e9 1909 assert(p - buf <= sizeof(buf));
ashleymills 0:ff9ebe0cf0e9 1910
ashleymills 0:ff9ebe0cf0e9 1911 return dtls_send_handshake_msg(ctx, peer, DTLS_HT_CERTIFICATE_REQUEST,
ashleymills 0:ff9ebe0cf0e9 1912 buf, p - buf);
ashleymills 0:ff9ebe0cf0e9 1913 }
ashleymills 0:ff9ebe0cf0e9 1914
ashleymills 0:ff9ebe0cf0e9 1915 static int
ashleymills 0:ff9ebe0cf0e9 1916 dtls_send_server_hello_done(dtls_context_t *ctx, dtls_peer_t *peer)
ashleymills 0:ff9ebe0cf0e9 1917 {
ashleymills 0:ff9ebe0cf0e9 1918
ashleymills 0:ff9ebe0cf0e9 1919 /* ServerHelloDone
ashleymills 0:ff9ebe0cf0e9 1920 *
ashleymills 0:ff9ebe0cf0e9 1921 * Start message construction at beginning of buffer. */
ashleymills 0:ff9ebe0cf0e9 1922
ashleymills 0:ff9ebe0cf0e9 1923 return dtls_send_handshake_msg(ctx, peer, DTLS_HT_SERVER_HELLO_DONE,
ashleymills 0:ff9ebe0cf0e9 1924 NULL, 0);
ashleymills 0:ff9ebe0cf0e9 1925 }
ashleymills 0:ff9ebe0cf0e9 1926
ashleymills 0:ff9ebe0cf0e9 1927 static int
ashleymills 0:ff9ebe0cf0e9 1928 dtls_send_server_hello_msgs(dtls_context_t *ctx, dtls_peer_t *peer)
ashleymills 0:ff9ebe0cf0e9 1929 {
ashleymills 0:ff9ebe0cf0e9 1930 int res;
ashleymills 0:ff9ebe0cf0e9 1931
ashleymills 0:ff9ebe0cf0e9 1932 res = dtls_send_server_hello(ctx, peer);
ashleymills 0:ff9ebe0cf0e9 1933
ashleymills 0:ff9ebe0cf0e9 1934 if (res < 0) {
ashleymills 0:ff9ebe0cf0e9 1935 DBG("dtls_server_hello: cannot prepare ServerHello record");
ashleymills 0:ff9ebe0cf0e9 1936 return res;
ashleymills 0:ff9ebe0cf0e9 1937 }
ashleymills 0:ff9ebe0cf0e9 1938
ashleymills 0:ff9ebe0cf0e9 1939 if (peer->handshake_params.cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8) {
ashleymills 0:ff9ebe0cf0e9 1940 const dtls_ecdsa_key_t *ecdsa_key;
ashleymills 0:ff9ebe0cf0e9 1941
ashleymills 0:ff9ebe0cf0e9 1942 res = CALL(ctx, get_ecdsa_key, &peer->session, &ecdsa_key);
ashleymills 0:ff9ebe0cf0e9 1943 if (res < 0) {
ashleymills 0:ff9ebe0cf0e9 1944 DBG("no ecdsa certificate to send in certificate");
ashleymills 0:ff9ebe0cf0e9 1945 return res;
ashleymills 0:ff9ebe0cf0e9 1946 }
ashleymills 0:ff9ebe0cf0e9 1947
ashleymills 0:ff9ebe0cf0e9 1948 res = dtls_send_certificate_ecdsa(ctx, peer, ecdsa_key);
ashleymills 0:ff9ebe0cf0e9 1949
ashleymills 0:ff9ebe0cf0e9 1950 if (res < 0) {
ashleymills 0:ff9ebe0cf0e9 1951 DBG("dtls_server_hello: cannot prepare Certificate record");
ashleymills 0:ff9ebe0cf0e9 1952 return res;
ashleymills 0:ff9ebe0cf0e9 1953 }
ashleymills 0:ff9ebe0cf0e9 1954
ashleymills 0:ff9ebe0cf0e9 1955 res = dtls_send_server_key_exchange_ecdh(ctx, peer, ecdsa_key);
ashleymills 0:ff9ebe0cf0e9 1956
ashleymills 0:ff9ebe0cf0e9 1957 if (res < 0) {
ashleymills 0:ff9ebe0cf0e9 1958 DBG("dtls_server_hello: cannot prepare Server Key Exchange record");
ashleymills 0:ff9ebe0cf0e9 1959 return res;
ashleymills 0:ff9ebe0cf0e9 1960 }
ashleymills 0:ff9ebe0cf0e9 1961
ashleymills 0:ff9ebe0cf0e9 1962 if (peer->handshake_params.cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 &&
ashleymills 0:ff9ebe0cf0e9 1963 ctx && ctx->h && ctx->h->verify_ecdsa_key) {
ashleymills 0:ff9ebe0cf0e9 1964 res = dtls_send_server_certificate_request(ctx, peer);
ashleymills 0:ff9ebe0cf0e9 1965
ashleymills 0:ff9ebe0cf0e9 1966 if (res < 0) {
ashleymills 0:ff9ebe0cf0e9 1967 DBG("dtls_server_hello: cannot prepare certificate Request record");
ashleymills 0:ff9ebe0cf0e9 1968 return res;
ashleymills 0:ff9ebe0cf0e9 1969 }
ashleymills 0:ff9ebe0cf0e9 1970 }
ashleymills 0:ff9ebe0cf0e9 1971 } else if (peer->handshake_params.cipher == TLS_PSK_WITH_AES_128_CCM_8) {
ashleymills 0:ff9ebe0cf0e9 1972 const dtls_psk_key_t *psk;
ashleymills 0:ff9ebe0cf0e9 1973
ashleymills 0:ff9ebe0cf0e9 1974 res = CALL(ctx, get_psk_key, &peer->session, NULL, 0, &psk);
ashleymills 0:ff9ebe0cf0e9 1975 if (res < 0) {
ashleymills 0:ff9ebe0cf0e9 1976 DBG("no psk or identity found for this session");
ashleymills 0:ff9ebe0cf0e9 1977 return res;
ashleymills 0:ff9ebe0cf0e9 1978 }
ashleymills 0:ff9ebe0cf0e9 1979
ashleymills 0:ff9ebe0cf0e9 1980 if (psk->id_length) {
ashleymills 0:ff9ebe0cf0e9 1981 res = dtls_send_server_key_exchange_psk(ctx, peer, psk);
ashleymills 0:ff9ebe0cf0e9 1982
ashleymills 0:ff9ebe0cf0e9 1983 if (res < 0) {
ashleymills 0:ff9ebe0cf0e9 1984 DBG("dtls_server_key_exchange_psk: cannot send server key exchange record");
ashleymills 0:ff9ebe0cf0e9 1985 return res;
ashleymills 0:ff9ebe0cf0e9 1986 }
ashleymills 0:ff9ebe0cf0e9 1987 }
ashleymills 0:ff9ebe0cf0e9 1988 }
ashleymills 0:ff9ebe0cf0e9 1989
ashleymills 0:ff9ebe0cf0e9 1990 res = dtls_send_server_hello_done(ctx, peer);
ashleymills 0:ff9ebe0cf0e9 1991
ashleymills 0:ff9ebe0cf0e9 1992 if (res < 0) {
ashleymills 0:ff9ebe0cf0e9 1993 DBG("dtls_server_hello: cannot prepare ServerHelloDone record");
ashleymills 0:ff9ebe0cf0e9 1994 return res;
ashleymills 0:ff9ebe0cf0e9 1995 }
ashleymills 0:ff9ebe0cf0e9 1996 return 0;
ashleymills 0:ff9ebe0cf0e9 1997 }
ashleymills 0:ff9ebe0cf0e9 1998
ashleymills 0:ff9ebe0cf0e9 1999 static inline int
ashleymills 0:ff9ebe0cf0e9 2000 dtls_send_ccs(dtls_context_t *ctx, dtls_peer_t *peer) {
ashleymills 0:ff9ebe0cf0e9 2001 uint8 buf[1];
ashleymills 0:ff9ebe0cf0e9 2002 buf[0] = 1;
ashleymills 0:ff9ebe0cf0e9 2003
ashleymills 0:ff9ebe0cf0e9 2004 return dtls_send(ctx, peer, DTLS_CT_CHANGE_CIPHER_SPEC, buf, 1);
ashleymills 0:ff9ebe0cf0e9 2005 }
ashleymills 0:ff9ebe0cf0e9 2006
ashleymills 0:ff9ebe0cf0e9 2007
ashleymills 0:ff9ebe0cf0e9 2008 static int
ashleymills 0:ff9ebe0cf0e9 2009 dtls_send_client_key_exchange(dtls_context_t *ctx, dtls_peer_t *peer)
ashleymills 0:ff9ebe0cf0e9 2010 {
ashleymills 0:ff9ebe0cf0e9 2011 uint8 buf[DTLS_CKXEC_LENGTH];
ashleymills 0:ff9ebe0cf0e9 2012 uint8 *p;
ashleymills 0:ff9ebe0cf0e9 2013 int err;
ashleymills 0:ff9ebe0cf0e9 2014 dtls_handshake_parameters_t *handshake = &peer->handshake_params;
ashleymills 0:ff9ebe0cf0e9 2015
ashleymills 0:ff9ebe0cf0e9 2016 p = buf;
ashleymills 0:ff9ebe0cf0e9 2017
ashleymills 0:ff9ebe0cf0e9 2018 switch (handshake->cipher) {
ashleymills 0:ff9ebe0cf0e9 2019 case TLS_PSK_WITH_AES_128_CCM_8: {
ashleymills 0:ff9ebe0cf0e9 2020 const dtls_psk_key_t *psk;
ashleymills 0:ff9ebe0cf0e9 2021
ashleymills 0:ff9ebe0cf0e9 2022 err = CALL(ctx, get_psk_key, &peer->session, handshake->keyx.psk.identity,
ashleymills 0:ff9ebe0cf0e9 2023 handshake->keyx.psk.id_length, &psk);
ashleymills 0:ff9ebe0cf0e9 2024 if (err < 0) {
ashleymills 0:ff9ebe0cf0e9 2025 DBG("no psk key to send in kx");
ashleymills 0:ff9ebe0cf0e9 2026 return err;
ashleymills 0:ff9ebe0cf0e9 2027 }
ashleymills 0:ff9ebe0cf0e9 2028
ashleymills 0:ff9ebe0cf0e9 2029 if (psk->id_length + sizeof(uint16) > DTLS_CKXEC_LENGTH) {
ashleymills 0:ff9ebe0cf0e9 2030 WARN("the psk identity is too long");
ashleymills 0:ff9ebe0cf0e9 2031 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
ashleymills 0:ff9ebe0cf0e9 2032 }
ashleymills 0:ff9ebe0cf0e9 2033
ashleymills 0:ff9ebe0cf0e9 2034 dtls_int_to_uint16(p, psk->id_length);
ashleymills 0:ff9ebe0cf0e9 2035 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 2036
ashleymills 0:ff9ebe0cf0e9 2037 memcpy(p, psk->id, psk->id_length);
ashleymills 0:ff9ebe0cf0e9 2038 p += psk->id_length;
ashleymills 0:ff9ebe0cf0e9 2039
ashleymills 0:ff9ebe0cf0e9 2040 break;
ashleymills 0:ff9ebe0cf0e9 2041 }
ashleymills 0:ff9ebe0cf0e9 2042 case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: {
ashleymills 0:ff9ebe0cf0e9 2043 uint8 *ephemeral_pub_x;
ashleymills 0:ff9ebe0cf0e9 2044 uint8 *ephemeral_pub_y;
ashleymills 0:ff9ebe0cf0e9 2045
ashleymills 0:ff9ebe0cf0e9 2046 dtls_int_to_uint8(p, 1 + 2 * DTLS_EC_KEY_SIZE);
ashleymills 0:ff9ebe0cf0e9 2047 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2048
ashleymills 0:ff9ebe0cf0e9 2049 /* This should be an uncompressed point, but I do not have access to the sepc. */
ashleymills 0:ff9ebe0cf0e9 2050 dtls_int_to_uint8(p, 4);
ashleymills 0:ff9ebe0cf0e9 2051 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2052
ashleymills 0:ff9ebe0cf0e9 2053 ephemeral_pub_x = p;
ashleymills 0:ff9ebe0cf0e9 2054 p += DTLS_EC_KEY_SIZE;
ashleymills 0:ff9ebe0cf0e9 2055 ephemeral_pub_y = p;
ashleymills 0:ff9ebe0cf0e9 2056 p += DTLS_EC_KEY_SIZE;
ashleymills 0:ff9ebe0cf0e9 2057
ashleymills 0:ff9ebe0cf0e9 2058 dtls_ecdsa_generate_key(peer->handshake_params.keyx.ecdsa.own_eph_priv,
ashleymills 0:ff9ebe0cf0e9 2059 ephemeral_pub_x, ephemeral_pub_y,
ashleymills 0:ff9ebe0cf0e9 2060 DTLS_EC_KEY_SIZE);
ashleymills 0:ff9ebe0cf0e9 2061
ashleymills 0:ff9ebe0cf0e9 2062 break;
ashleymills 0:ff9ebe0cf0e9 2063 }
ashleymills 0:ff9ebe0cf0e9 2064 default:
ashleymills 0:ff9ebe0cf0e9 2065 DBG("cipher not supported");
ashleymills 0:ff9ebe0cf0e9 2066 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
ashleymills 0:ff9ebe0cf0e9 2067 }
ashleymills 0:ff9ebe0cf0e9 2068
ashleymills 0:ff9ebe0cf0e9 2069 assert(p - buf <= sizeof(buf));
ashleymills 0:ff9ebe0cf0e9 2070
ashleymills 0:ff9ebe0cf0e9 2071 return dtls_send_handshake_msg(ctx, peer, DTLS_HT_CLIENT_KEY_EXCHANGE,
ashleymills 0:ff9ebe0cf0e9 2072 buf, p - buf);
ashleymills 0:ff9ebe0cf0e9 2073 }
ashleymills 0:ff9ebe0cf0e9 2074
ashleymills 0:ff9ebe0cf0e9 2075 static int
ashleymills 0:ff9ebe0cf0e9 2076 dtls_send_certificate_verify_ecdh(dtls_context_t *ctx, dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 2077 const dtls_ecdsa_key_t *key)
ashleymills 0:ff9ebe0cf0e9 2078 {
ashleymills 0:ff9ebe0cf0e9 2079 /* The ASN.1 Integer representation of an 32 byte unsigned int could be
ashleymills 0:ff9ebe0cf0e9 2080 * 33 bytes long add space for that */
ashleymills 0:ff9ebe0cf0e9 2081 uint8 buf[DTLS_CV_LENGTH + 2];
ashleymills 0:ff9ebe0cf0e9 2082 uint8 *p;
ashleymills 0:ff9ebe0cf0e9 2083 uint32_t point_r[9];
ashleymills 0:ff9ebe0cf0e9 2084 uint32_t point_s[9];
ashleymills 0:ff9ebe0cf0e9 2085 dtls_hash_ctx hs_hash;
ashleymills 0:ff9ebe0cf0e9 2086 unsigned char sha256hash[DTLS_HMAC_DIGEST_SIZE];
ashleymills 0:ff9ebe0cf0e9 2087
ashleymills 0:ff9ebe0cf0e9 2088 /* ServerKeyExchange
ashleymills 0:ff9ebe0cf0e9 2089 *
ashleymills 0:ff9ebe0cf0e9 2090 * Start message construction at beginning of buffer. */
ashleymills 0:ff9ebe0cf0e9 2091 p = buf;
ashleymills 0:ff9ebe0cf0e9 2092
ashleymills 0:ff9ebe0cf0e9 2093 /* sha256 */
ashleymills 0:ff9ebe0cf0e9 2094 dtls_int_to_uint8(p, TLS_EXT_SIG_HASH_ALGO_SHA256);
ashleymills 0:ff9ebe0cf0e9 2095 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2096
ashleymills 0:ff9ebe0cf0e9 2097 /* ecdsa */
ashleymills 0:ff9ebe0cf0e9 2098 dtls_int_to_uint8(p, TLS_EXT_SIG_HASH_ALGO_ECDSA);
ashleymills 0:ff9ebe0cf0e9 2099 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2100
ashleymills 0:ff9ebe0cf0e9 2101 copy_hs_hash(peer, &hs_hash);
ashleymills 0:ff9ebe0cf0e9 2102
ashleymills 0:ff9ebe0cf0e9 2103 dtls_hash_finalize(sha256hash, &hs_hash);
ashleymills 0:ff9ebe0cf0e9 2104
ashleymills 0:ff9ebe0cf0e9 2105 /* sign the ephemeral and its paramaters */
ashleymills 0:ff9ebe0cf0e9 2106 dtls_ecdsa_create_sig_hash(key->priv_key, DTLS_EC_KEY_SIZE,
ashleymills 0:ff9ebe0cf0e9 2107 sha256hash, sizeof(sha256hash),
ashleymills 0:ff9ebe0cf0e9 2108 point_r, point_s);
ashleymills 0:ff9ebe0cf0e9 2109
ashleymills 0:ff9ebe0cf0e9 2110 p = dtls_add_ecdsa_signature_elem(p, point_r, point_s);
ashleymills 0:ff9ebe0cf0e9 2111
ashleymills 0:ff9ebe0cf0e9 2112 assert(p - buf <= sizeof(buf));
ashleymills 0:ff9ebe0cf0e9 2113
ashleymills 0:ff9ebe0cf0e9 2114 return dtls_send_handshake_msg(ctx, peer, DTLS_HT_CERTIFICATE_VERIFY,
ashleymills 0:ff9ebe0cf0e9 2115 buf, p - buf);
ashleymills 0:ff9ebe0cf0e9 2116 }
ashleymills 0:ff9ebe0cf0e9 2117
ashleymills 0:ff9ebe0cf0e9 2118 static int
ashleymills 0:ff9ebe0cf0e9 2119 dtls_send_finished(dtls_context_t *ctx, dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 2120 const unsigned char *label, size_t labellen)
ashleymills 0:ff9ebe0cf0e9 2121 {
ashleymills 0:ff9ebe0cf0e9 2122 int length;
ashleymills 0:ff9ebe0cf0e9 2123 uint8 hash[DTLS_HMAC_MAX];
ashleymills 0:ff9ebe0cf0e9 2124 uint8 buf[DTLS_FIN_LENGTH];
ashleymills 0:ff9ebe0cf0e9 2125 dtls_hash_ctx hs_hash;
ashleymills 0:ff9ebe0cf0e9 2126 uint8 *p = buf;
ashleymills 0:ff9ebe0cf0e9 2127
ashleymills 0:ff9ebe0cf0e9 2128 copy_hs_hash(peer, &hs_hash);
ashleymills 0:ff9ebe0cf0e9 2129
ashleymills 0:ff9ebe0cf0e9 2130 length = dtls_hash_finalize(hash, &hs_hash);
ashleymills 0:ff9ebe0cf0e9 2131
ashleymills 0:ff9ebe0cf0e9 2132 dtls_prf(peer->handshake_params.tmp.master_secret,
ashleymills 0:ff9ebe0cf0e9 2133 DTLS_MASTER_SECRET_LENGTH,
ashleymills 0:ff9ebe0cf0e9 2134 label, labellen,
ashleymills 0:ff9ebe0cf0e9 2135 PRF_LABEL(finished), PRF_LABEL_SIZE(finished),
ashleymills 0:ff9ebe0cf0e9 2136 hash, length,
ashleymills 0:ff9ebe0cf0e9 2137 p, DTLS_FIN_LENGTH);
ashleymills 0:ff9ebe0cf0e9 2138
ashleymills 0:ff9ebe0cf0e9 2139 dtls_dsrv_hexdump_log(LOG_DEBUG, "server finished MAC", p, DTLS_FIN_LENGTH, 0);
ashleymills 0:ff9ebe0cf0e9 2140
ashleymills 0:ff9ebe0cf0e9 2141 p += DTLS_FIN_LENGTH;
ashleymills 0:ff9ebe0cf0e9 2142
ashleymills 0:ff9ebe0cf0e9 2143 assert(p - buf <= sizeof(buf));
ashleymills 0:ff9ebe0cf0e9 2144
ashleymills 0:ff9ebe0cf0e9 2145 return dtls_send_handshake_msg(ctx, peer, DTLS_HT_FINISHED,
ashleymills 0:ff9ebe0cf0e9 2146 buf, p - buf);
ashleymills 0:ff9ebe0cf0e9 2147 }
ashleymills 0:ff9ebe0cf0e9 2148
ashleymills 0:ff9ebe0cf0e9 2149 static int
ashleymills 0:ff9ebe0cf0e9 2150 dtls_send_client_hello(dtls_context_t *ctx, dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 2151 uint8 cookie[], size_t cookie_length) {
ashleymills 0:ff9ebe0cf0e9 2152 DBG("dtls_send_client_hello");
ashleymills 0:ff9ebe0cf0e9 2153 uint8 buf[DTLS_CH_LENGTH_MAX];
ashleymills 0:ff9ebe0cf0e9 2154 uint8 *p = buf;
ashleymills 0:ff9ebe0cf0e9 2155 uint8_t cipher_size;
ashleymills 0:ff9ebe0cf0e9 2156 uint8_t extension_size;
ashleymills 0:ff9ebe0cf0e9 2157 int psk;
ashleymills 0:ff9ebe0cf0e9 2158 int ecdsa;
ashleymills 0:ff9ebe0cf0e9 2159 dtls_handshake_parameters_t *handshake = &peer->handshake_params;
ashleymills 0:ff9ebe0cf0e9 2160 dtls_tick_t now;
ashleymills 0:ff9ebe0cf0e9 2161
ashleymills 0:ff9ebe0cf0e9 2162 psk = is_psk_supported(ctx);
ashleymills 0:ff9ebe0cf0e9 2163 ecdsa = is_ecdsa_supported(ctx, 1);
ashleymills 0:ff9ebe0cf0e9 2164
ashleymills 0:ff9ebe0cf0e9 2165 cipher_size = 2 + ((ecdsa) ? 2 : 0) + ((psk) ? 2 : 0);
ashleymills 0:ff9ebe0cf0e9 2166 extension_size = (ecdsa) ? 2 + 6 + 6 + 8 + 6: 0;
ashleymills 0:ff9ebe0cf0e9 2167
ashleymills 0:ff9ebe0cf0e9 2168 if (cipher_size == 0) {
ashleymills 0:ff9ebe0cf0e9 2169 DBG("no cipher callbacks implemented");
ashleymills 0:ff9ebe0cf0e9 2170 }
ashleymills 0:ff9ebe0cf0e9 2171
ashleymills 0:ff9ebe0cf0e9 2172 dtls_int_to_uint16(p, DTLS_VERSION);
ashleymills 0:ff9ebe0cf0e9 2173 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 2174
ashleymills 0:ff9ebe0cf0e9 2175 if (cookie_length > DTLS_COOKIE_LENGTH_MAX) {
ashleymills 0:ff9ebe0cf0e9 2176 WARN("the cookie is too long");
ashleymills 0:ff9ebe0cf0e9 2177 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 2178 }
ashleymills 0:ff9ebe0cf0e9 2179
ashleymills 0:ff9ebe0cf0e9 2180 if (cookie_length == 0) {
ashleymills 0:ff9ebe0cf0e9 2181 /* Set client random: First 4 bytes are the client's Unix timestamp,
ashleymills 0:ff9ebe0cf0e9 2182 * followed by 28 bytes of generate random data. */
ashleymills 0:ff9ebe0cf0e9 2183 dtls_ticks(&now);
ashleymills 0:ff9ebe0cf0e9 2184 dtls_int_to_uint32(&handshake->tmp.random.client, now / CLOCK_SECOND);
ashleymills 0:ff9ebe0cf0e9 2185 prng(handshake->tmp.random.client + sizeof(uint32),
ashleymills 0:ff9ebe0cf0e9 2186 DTLS_RANDOM_LENGTH - sizeof(uint32));
ashleymills 0:ff9ebe0cf0e9 2187 }
ashleymills 0:ff9ebe0cf0e9 2188 /* we must use the same Client Random as for the previous request */
ashleymills 0:ff9ebe0cf0e9 2189 memcpy(p, handshake->tmp.random.client, DTLS_RANDOM_LENGTH);
ashleymills 0:ff9ebe0cf0e9 2190 p += DTLS_RANDOM_LENGTH;
ashleymills 0:ff9ebe0cf0e9 2191
ashleymills 0:ff9ebe0cf0e9 2192 /* session id (length 0) */
ashleymills 0:ff9ebe0cf0e9 2193 dtls_int_to_uint8(p, 0);
ashleymills 0:ff9ebe0cf0e9 2194 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2195
ashleymills 0:ff9ebe0cf0e9 2196 /* cookie */
ashleymills 0:ff9ebe0cf0e9 2197 dtls_int_to_uint8(p, cookie_length);
ashleymills 0:ff9ebe0cf0e9 2198 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2199 if (cookie_length != 0) {
ashleymills 0:ff9ebe0cf0e9 2200 memcpy(p, cookie, cookie_length);
ashleymills 0:ff9ebe0cf0e9 2201 p += cookie_length;
ashleymills 0:ff9ebe0cf0e9 2202 }
ashleymills 0:ff9ebe0cf0e9 2203
ashleymills 0:ff9ebe0cf0e9 2204 /* add known cipher(s) */
ashleymills 0:ff9ebe0cf0e9 2205 dtls_int_to_uint16(p, cipher_size - 2);
ashleymills 0:ff9ebe0cf0e9 2206 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 2207
ashleymills 0:ff9ebe0cf0e9 2208 if (ecdsa) {
ashleymills 0:ff9ebe0cf0e9 2209 dtls_int_to_uint16(p, TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
ashleymills 0:ff9ebe0cf0e9 2210 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 2211 }
ashleymills 0:ff9ebe0cf0e9 2212 if (psk) {
ashleymills 0:ff9ebe0cf0e9 2213 dtls_int_to_uint16(p, TLS_PSK_WITH_AES_128_CCM_8);
ashleymills 0:ff9ebe0cf0e9 2214 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 2215 }
ashleymills 0:ff9ebe0cf0e9 2216
ashleymills 0:ff9ebe0cf0e9 2217 /* compression method */
ashleymills 0:ff9ebe0cf0e9 2218 dtls_int_to_uint8(p, 1);
ashleymills 0:ff9ebe0cf0e9 2219 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2220
ashleymills 0:ff9ebe0cf0e9 2221 dtls_int_to_uint8(p, TLS_COMPRESSION_NULL);
ashleymills 0:ff9ebe0cf0e9 2222 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2223
ashleymills 0:ff9ebe0cf0e9 2224 if (extension_size) {
ashleymills 0:ff9ebe0cf0e9 2225 /* length of the extensions */
ashleymills 0:ff9ebe0cf0e9 2226 dtls_int_to_uint16(p, extension_size - 2);
ashleymills 0:ff9ebe0cf0e9 2227 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 2228 }
ashleymills 0:ff9ebe0cf0e9 2229
ashleymills 0:ff9ebe0cf0e9 2230 if (ecdsa) {
ashleymills 0:ff9ebe0cf0e9 2231 /* client certificate type extension */
ashleymills 0:ff9ebe0cf0e9 2232 dtls_int_to_uint16(p, TLS_EXT_CLIENT_CERIFICATE_TYPE);
ashleymills 0:ff9ebe0cf0e9 2233 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 2234
ashleymills 0:ff9ebe0cf0e9 2235 /* length of this extension type */
ashleymills 0:ff9ebe0cf0e9 2236 dtls_int_to_uint16(p, 2);
ashleymills 0:ff9ebe0cf0e9 2237 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 2238
ashleymills 0:ff9ebe0cf0e9 2239 /* length of the list */
ashleymills 0:ff9ebe0cf0e9 2240 dtls_int_to_uint8(p, 1);
ashleymills 0:ff9ebe0cf0e9 2241 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2242
ashleymills 0:ff9ebe0cf0e9 2243 dtls_int_to_uint8(p, TLS_CERT_TYPE_OOB);
ashleymills 0:ff9ebe0cf0e9 2244 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2245
ashleymills 0:ff9ebe0cf0e9 2246 /* client certificate type extension */
ashleymills 0:ff9ebe0cf0e9 2247 dtls_int_to_uint16(p, TLS_EXT_SERVER_CERIFICATE_TYPE);
ashleymills 0:ff9ebe0cf0e9 2248 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 2249
ashleymills 0:ff9ebe0cf0e9 2250 /* length of this extension type */
ashleymills 0:ff9ebe0cf0e9 2251 dtls_int_to_uint16(p, 2);
ashleymills 0:ff9ebe0cf0e9 2252 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 2253
ashleymills 0:ff9ebe0cf0e9 2254 /* length of the list */
ashleymills 0:ff9ebe0cf0e9 2255 dtls_int_to_uint8(p, 1);
ashleymills 0:ff9ebe0cf0e9 2256 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2257
ashleymills 0:ff9ebe0cf0e9 2258 dtls_int_to_uint8(p, TLS_CERT_TYPE_OOB);
ashleymills 0:ff9ebe0cf0e9 2259 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2260
ashleymills 0:ff9ebe0cf0e9 2261 /* elliptic_curves */
ashleymills 0:ff9ebe0cf0e9 2262 dtls_int_to_uint16(p, TLS_EXT_ELLIPTIC_CURVES);
ashleymills 0:ff9ebe0cf0e9 2263 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 2264
ashleymills 0:ff9ebe0cf0e9 2265 /* length of this extension type */
ashleymills 0:ff9ebe0cf0e9 2266 dtls_int_to_uint16(p, 4);
ashleymills 0:ff9ebe0cf0e9 2267 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 2268
ashleymills 0:ff9ebe0cf0e9 2269 /* length of the list */
ashleymills 0:ff9ebe0cf0e9 2270 dtls_int_to_uint16(p, 2);
ashleymills 0:ff9ebe0cf0e9 2271 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 2272
ashleymills 0:ff9ebe0cf0e9 2273 dtls_int_to_uint16(p, TLS_EXT_ELLIPTIC_CURVES_SECP256R1);
ashleymills 0:ff9ebe0cf0e9 2274 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 2275
ashleymills 0:ff9ebe0cf0e9 2276 /* ec_point_formats */
ashleymills 0:ff9ebe0cf0e9 2277 dtls_int_to_uint16(p, TLS_EXT_EC_POINT_FORMATS);
ashleymills 0:ff9ebe0cf0e9 2278 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 2279
ashleymills 0:ff9ebe0cf0e9 2280 /* length of this extension type */
ashleymills 0:ff9ebe0cf0e9 2281 dtls_int_to_uint16(p, 2);
ashleymills 0:ff9ebe0cf0e9 2282 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 2283
ashleymills 0:ff9ebe0cf0e9 2284 /* number of supported formats */
ashleymills 0:ff9ebe0cf0e9 2285 dtls_int_to_uint8(p, 1);
ashleymills 0:ff9ebe0cf0e9 2286 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2287
ashleymills 0:ff9ebe0cf0e9 2288 dtls_int_to_uint8(p, TLS_EXT_EC_POINT_FORMATS_UNCOMPRESSED);
ashleymills 0:ff9ebe0cf0e9 2289 p += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2290 }
ashleymills 0:ff9ebe0cf0e9 2291
ashleymills 0:ff9ebe0cf0e9 2292 assert(p - buf <= sizeof(buf));
ashleymills 0:ff9ebe0cf0e9 2293
ashleymills 0:ff9ebe0cf0e9 2294 if (cookie_length != 0)
ashleymills 0:ff9ebe0cf0e9 2295 clear_hs_hash(peer);
ashleymills 0:ff9ebe0cf0e9 2296
ashleymills 0:ff9ebe0cf0e9 2297 return dtls_send_handshake_msg_hash(ctx, peer, &peer->session,
ashleymills 0:ff9ebe0cf0e9 2298 DTLS_HT_CLIENT_HELLO,
ashleymills 0:ff9ebe0cf0e9 2299 buf, p - buf, cookie_length != 0);
ashleymills 0:ff9ebe0cf0e9 2300 }
ashleymills 0:ff9ebe0cf0e9 2301
ashleymills 0:ff9ebe0cf0e9 2302 static int
ashleymills 0:ff9ebe0cf0e9 2303 check_server_hello(dtls_context_t *ctx,
ashleymills 0:ff9ebe0cf0e9 2304 dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 2305 uint8 *data, size_t data_length)
ashleymills 0:ff9ebe0cf0e9 2306 {
ashleymills 0:ff9ebe0cf0e9 2307 dtls_handshake_parameters_t *handshake = &peer->handshake_params;
ashleymills 0:ff9ebe0cf0e9 2308
ashleymills 0:ff9ebe0cf0e9 2309 /* This function is called when we expect a ServerHello (i.e. we
ashleymills 0:ff9ebe0cf0e9 2310 * have sent a ClientHello). We might instead receive a HelloVerify
ashleymills 0:ff9ebe0cf0e9 2311 * request containing a cookie. If so, we must repeat the
ashleymills 0:ff9ebe0cf0e9 2312 * ClientHello with the given Cookie.
ashleymills 0:ff9ebe0cf0e9 2313 */
ashleymills 0:ff9ebe0cf0e9 2314 if (data_length < DTLS_HS_LENGTH + DTLS_HS_LENGTH)
ashleymills 0:ff9ebe0cf0e9 2315 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 2316
ashleymills 0:ff9ebe0cf0e9 2317 update_hs_hash(peer, data, data_length);
ashleymills 0:ff9ebe0cf0e9 2318
ashleymills 0:ff9ebe0cf0e9 2319 /* FIXME: check data_length before accessing fields */
ashleymills 0:ff9ebe0cf0e9 2320
ashleymills 0:ff9ebe0cf0e9 2321 /* Get the server's random data and store selected cipher suite
ashleymills 0:ff9ebe0cf0e9 2322 * and compression method (like dtls_update_parameters().
ashleymills 0:ff9ebe0cf0e9 2323 * Then calculate master secret and wait for ServerHelloDone. When received,
ashleymills 0:ff9ebe0cf0e9 2324 * send ClientKeyExchange (?) and ChangeCipherSpec + ClientFinished. */
ashleymills 0:ff9ebe0cf0e9 2325
ashleymills 0:ff9ebe0cf0e9 2326 /* check server version */
ashleymills 0:ff9ebe0cf0e9 2327 data += DTLS_HS_LENGTH;
ashleymills 0:ff9ebe0cf0e9 2328 data_length -= DTLS_HS_LENGTH;
ashleymills 0:ff9ebe0cf0e9 2329
ashleymills 0:ff9ebe0cf0e9 2330 if (dtls_uint16_to_int(data) != DTLS_VERSION) {
ashleymills 0:ff9ebe0cf0e9 2331 DBG("unknown DTLS version");
ashleymills 0:ff9ebe0cf0e9 2332 return dtls_alert_fatal_create(DTLS_ALERT_PROTOCOL_VERSION);
ashleymills 0:ff9ebe0cf0e9 2333 }
ashleymills 0:ff9ebe0cf0e9 2334
ashleymills 0:ff9ebe0cf0e9 2335 data += sizeof(uint16); /* skip version field */
ashleymills 0:ff9ebe0cf0e9 2336 data_length -= sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 2337
ashleymills 0:ff9ebe0cf0e9 2338 /* store server random data */
ashleymills 0:ff9ebe0cf0e9 2339 memcpy(handshake->tmp.random.server, data, DTLS_RANDOM_LENGTH);
ashleymills 0:ff9ebe0cf0e9 2340 /* skip server random */
ashleymills 0:ff9ebe0cf0e9 2341 data += DTLS_RANDOM_LENGTH;
ashleymills 0:ff9ebe0cf0e9 2342 data_length -= DTLS_RANDOM_LENGTH;
ashleymills 0:ff9ebe0cf0e9 2343
ashleymills 0:ff9ebe0cf0e9 2344 SKIP_VAR_FIELD(data, data_length, uint8); /* skip session id */
ashleymills 0:ff9ebe0cf0e9 2345
ashleymills 0:ff9ebe0cf0e9 2346 /* Check cipher suite. As we offer all we have, it is sufficient
ashleymills 0:ff9ebe0cf0e9 2347 * to check if the cipher suite selected by the server is in our
ashleymills 0:ff9ebe0cf0e9 2348 * list of known cipher suites. Subsets are not supported. */
ashleymills 0:ff9ebe0cf0e9 2349 handshake->cipher = dtls_uint16_to_int(data);
ashleymills 0:ff9ebe0cf0e9 2350 if (!known_cipher(ctx, handshake->cipher, 1)) {
ashleymills 0:ff9ebe0cf0e9 2351 DBG("unsupported cipher 0x%02x 0x%02x",
ashleymills 0:ff9ebe0cf0e9 2352 data[0], data[1]);
ashleymills 0:ff9ebe0cf0e9 2353 return dtls_alert_fatal_create(DTLS_ALERT_INSUFFICIENT_SECURITY);
ashleymills 0:ff9ebe0cf0e9 2354 }
ashleymills 0:ff9ebe0cf0e9 2355 data += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 2356 data_length -= sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 2357
ashleymills 0:ff9ebe0cf0e9 2358 /* Check if NULL compression was selected. We do not know any other. */
ashleymills 0:ff9ebe0cf0e9 2359 if (dtls_uint8_to_int(data) != TLS_COMPRESSION_NULL) {
ashleymills 0:ff9ebe0cf0e9 2360 DBG("unsupported compression method 0x%02x", data[0]);
ashleymills 0:ff9ebe0cf0e9 2361 return dtls_alert_fatal_create(DTLS_ALERT_INSUFFICIENT_SECURITY);
ashleymills 0:ff9ebe0cf0e9 2362 }
ashleymills 0:ff9ebe0cf0e9 2363 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2364 data_length -= sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2365
ashleymills 0:ff9ebe0cf0e9 2366 return dtls_check_tls_extension(peer, data, data_length, 0);
ashleymills 0:ff9ebe0cf0e9 2367
ashleymills 0:ff9ebe0cf0e9 2368 error:
ashleymills 0:ff9ebe0cf0e9 2369 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 2370 }
ashleymills 0:ff9ebe0cf0e9 2371
ashleymills 0:ff9ebe0cf0e9 2372 static int
ashleymills 0:ff9ebe0cf0e9 2373 check_server_hello_verify_request(dtls_context_t *ctx,
ashleymills 0:ff9ebe0cf0e9 2374 dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 2375 uint8 *data, size_t data_length)
ashleymills 0:ff9ebe0cf0e9 2376 {
ashleymills 0:ff9ebe0cf0e9 2377 DBG("check_server_hello_verify_request");
ashleymills 0:ff9ebe0cf0e9 2378 dtls_hello_verify_t *hv;
ashleymills 0:ff9ebe0cf0e9 2379 int res;
ashleymills 0:ff9ebe0cf0e9 2380
ashleymills 0:ff9ebe0cf0e9 2381 if (data_length < DTLS_HS_LENGTH + DTLS_HV_LENGTH)
ashleymills 0:ff9ebe0cf0e9 2382 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 2383
ashleymills 0:ff9ebe0cf0e9 2384 hv = (dtls_hello_verify_t *)(data + DTLS_HS_LENGTH);
ashleymills 0:ff9ebe0cf0e9 2385
ashleymills 0:ff9ebe0cf0e9 2386 res = dtls_send_client_hello(ctx, peer, hv->cookie, hv->cookie_length);
ashleymills 0:ff9ebe0cf0e9 2387
ashleymills 0:ff9ebe0cf0e9 2388 if (res < 0)
ashleymills 0:ff9ebe0cf0e9 2389 WARN("cannot send ClientHello");
ashleymills 0:ff9ebe0cf0e9 2390
ashleymills 0:ff9ebe0cf0e9 2391 return res;
ashleymills 0:ff9ebe0cf0e9 2392 }
ashleymills 0:ff9ebe0cf0e9 2393
ashleymills 0:ff9ebe0cf0e9 2394 static int
ashleymills 0:ff9ebe0cf0e9 2395 check_server_certificate(dtls_context_t *ctx,
ashleymills 0:ff9ebe0cf0e9 2396 dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 2397 uint8 *data, size_t data_length)
ashleymills 0:ff9ebe0cf0e9 2398 {
ashleymills 0:ff9ebe0cf0e9 2399 DBG("check_server_certificate");
ashleymills 0:ff9ebe0cf0e9 2400 int err;
ashleymills 0:ff9ebe0cf0e9 2401 dtls_handshake_parameters_t *config = &peer->handshake_params;
ashleymills 0:ff9ebe0cf0e9 2402
ashleymills 0:ff9ebe0cf0e9 2403 update_hs_hash(peer, data, data_length);
ashleymills 0:ff9ebe0cf0e9 2404
ashleymills 0:ff9ebe0cf0e9 2405 assert(config->cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
ashleymills 0:ff9ebe0cf0e9 2406
ashleymills 0:ff9ebe0cf0e9 2407 data += DTLS_HS_LENGTH;
ashleymills 0:ff9ebe0cf0e9 2408
ashleymills 0:ff9ebe0cf0e9 2409 if (dtls_uint24_to_int(data) != 94) {
ashleymills 0:ff9ebe0cf0e9 2410 DBG("expect length of 94 bytes for server certificate message");
ashleymills 0:ff9ebe0cf0e9 2411 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 2412 }
ashleymills 0:ff9ebe0cf0e9 2413 data += sizeof(uint24);
ashleymills 0:ff9ebe0cf0e9 2414
ashleymills 0:ff9ebe0cf0e9 2415 if (dtls_uint24_to_int(data) != 91) {
ashleymills 0:ff9ebe0cf0e9 2416 DBG("expect length of 91 bytes for certificate");
ashleymills 0:ff9ebe0cf0e9 2417 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 2418 }
ashleymills 0:ff9ebe0cf0e9 2419 data += sizeof(uint24);
ashleymills 0:ff9ebe0cf0e9 2420
ashleymills 0:ff9ebe0cf0e9 2421 if (memcmp(data, cert_asn1_header, sizeof(cert_asn1_header))) {
ashleymills 0:ff9ebe0cf0e9 2422 DBG("got an unexpected Subject public key format");
ashleymills 0:ff9ebe0cf0e9 2423 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 2424 }
ashleymills 0:ff9ebe0cf0e9 2425 data += sizeof(cert_asn1_header);
ashleymills 0:ff9ebe0cf0e9 2426
ashleymills 0:ff9ebe0cf0e9 2427 memcpy(config->keyx.ecdsa.other_pub_x, data,
ashleymills 0:ff9ebe0cf0e9 2428 sizeof(config->keyx.ecdsa.other_pub_x));
ashleymills 0:ff9ebe0cf0e9 2429 data += sizeof(config->keyx.ecdsa.other_pub_x);
ashleymills 0:ff9ebe0cf0e9 2430
ashleymills 0:ff9ebe0cf0e9 2431 memcpy(config->keyx.ecdsa.other_pub_y, data,
ashleymills 0:ff9ebe0cf0e9 2432 sizeof(config->keyx.ecdsa.other_pub_y));
ashleymills 0:ff9ebe0cf0e9 2433 data += sizeof(config->keyx.ecdsa.other_pub_y);
ashleymills 0:ff9ebe0cf0e9 2434
ashleymills 0:ff9ebe0cf0e9 2435 err = CALL(ctx, verify_ecdsa_key, &peer->session,
ashleymills 0:ff9ebe0cf0e9 2436 config->keyx.ecdsa.other_pub_x,
ashleymills 0:ff9ebe0cf0e9 2437 config->keyx.ecdsa.other_pub_y,
ashleymills 0:ff9ebe0cf0e9 2438 sizeof(config->keyx.ecdsa.other_pub_x));
ashleymills 0:ff9ebe0cf0e9 2439 if (err < 0) {
ashleymills 0:ff9ebe0cf0e9 2440 WARN("The certificate was not accepted");
ashleymills 0:ff9ebe0cf0e9 2441 return err;
ashleymills 0:ff9ebe0cf0e9 2442 }
ashleymills 0:ff9ebe0cf0e9 2443
ashleymills 0:ff9ebe0cf0e9 2444 return 0;
ashleymills 0:ff9ebe0cf0e9 2445 }
ashleymills 0:ff9ebe0cf0e9 2446
ashleymills 0:ff9ebe0cf0e9 2447 static int
ashleymills 0:ff9ebe0cf0e9 2448 check_server_key_exchange_ecdsa(dtls_context_t *ctx,
ashleymills 0:ff9ebe0cf0e9 2449 dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 2450 uint8 *data, size_t data_length)
ashleymills 0:ff9ebe0cf0e9 2451 {
ashleymills 0:ff9ebe0cf0e9 2452 DBG("check_server_key_exchange_ecdsa");
ashleymills 0:ff9ebe0cf0e9 2453
ashleymills 0:ff9ebe0cf0e9 2454 dtls_handshake_parameters_t *config = &peer->handshake_params;
ashleymills 0:ff9ebe0cf0e9 2455 int i;
ashleymills 0:ff9ebe0cf0e9 2456 unsigned char *result_r;
ashleymills 0:ff9ebe0cf0e9 2457 unsigned char *result_s;
ashleymills 0:ff9ebe0cf0e9 2458 unsigned char *key_params;
ashleymills 0:ff9ebe0cf0e9 2459
ashleymills 0:ff9ebe0cf0e9 2460 update_hs_hash(peer, data, data_length);
ashleymills 0:ff9ebe0cf0e9 2461
ashleymills 0:ff9ebe0cf0e9 2462 assert(config->cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
ashleymills 0:ff9ebe0cf0e9 2463
ashleymills 0:ff9ebe0cf0e9 2464 data += DTLS_HS_LENGTH;
ashleymills 0:ff9ebe0cf0e9 2465
ashleymills 0:ff9ebe0cf0e9 2466 if (data_length < DTLS_HS_LENGTH + DTLS_SKEXEC_LENGTH) {
ashleymills 0:ff9ebe0cf0e9 2467 DBG("the package length does not match the expected");
ashleymills 0:ff9ebe0cf0e9 2468 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 2469 }
ashleymills 0:ff9ebe0cf0e9 2470 key_params = data;
ashleymills 0:ff9ebe0cf0e9 2471
ashleymills 0:ff9ebe0cf0e9 2472 if (dtls_uint8_to_int(data) != 3) {
ashleymills 0:ff9ebe0cf0e9 2473 DBG("Only named curves supported");
ashleymills 0:ff9ebe0cf0e9 2474 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 2475 }
ashleymills 0:ff9ebe0cf0e9 2476 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2477 data_length -= sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2478
ashleymills 0:ff9ebe0cf0e9 2479 if (dtls_uint16_to_int(data) != 23) {
ashleymills 0:ff9ebe0cf0e9 2480 DBG("secp256r1 supported");
ashleymills 0:ff9ebe0cf0e9 2481 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 2482 }
ashleymills 0:ff9ebe0cf0e9 2483 data += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 2484 data_length -= sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 2485
ashleymills 0:ff9ebe0cf0e9 2486 if (dtls_uint8_to_int(data) != 65) {
ashleymills 0:ff9ebe0cf0e9 2487 DBG("expected 65 bytes long public point");
ashleymills 0:ff9ebe0cf0e9 2488 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 2489 }
ashleymills 0:ff9ebe0cf0e9 2490 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2491 data_length -= sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2492
ashleymills 0:ff9ebe0cf0e9 2493 if (dtls_uint8_to_int(data) != 4) {
ashleymills 0:ff9ebe0cf0e9 2494 DBG("expected uncompressed public point");
ashleymills 0:ff9ebe0cf0e9 2495 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 2496 }
ashleymills 0:ff9ebe0cf0e9 2497 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2498 data_length -= sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2499
ashleymills 0:ff9ebe0cf0e9 2500 memcpy(config->keyx.ecdsa.other_eph_pub_x, data, sizeof(config->keyx.ecdsa.other_eph_pub_y));
ashleymills 0:ff9ebe0cf0e9 2501 data += sizeof(config->keyx.ecdsa.other_eph_pub_y);
ashleymills 0:ff9ebe0cf0e9 2502 data_length -= sizeof(config->keyx.ecdsa.other_eph_pub_y);
ashleymills 0:ff9ebe0cf0e9 2503
ashleymills 0:ff9ebe0cf0e9 2504 memcpy(config->keyx.ecdsa.other_eph_pub_y, data, sizeof(config->keyx.ecdsa.other_eph_pub_y));
ashleymills 0:ff9ebe0cf0e9 2505 data += sizeof(config->keyx.ecdsa.other_eph_pub_y);
ashleymills 0:ff9ebe0cf0e9 2506 data_length -= sizeof(config->keyx.ecdsa.other_eph_pub_y);
ashleymills 0:ff9ebe0cf0e9 2507
ashleymills 0:ff9ebe0cf0e9 2508
ashleymills 0:ff9ebe0cf0e9 2509 if (data_length < dtls_uint16_to_int(data)) {
ashleymills 0:ff9ebe0cf0e9 2510 DBG("signature length wrong");
ashleymills 0:ff9ebe0cf0e9 2511 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 2512 }
ashleymills 0:ff9ebe0cf0e9 2513 data += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 2514 data_length -= sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 2515
ashleymills 0:ff9ebe0cf0e9 2516 if (dtls_uint8_to_int(data) != 0x30) {
ashleymills 0:ff9ebe0cf0e9 2517 DBG("wrong ASN.1 struct, expected SEQUENCE");
ashleymills 0:ff9ebe0cf0e9 2518 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 2519 }
ashleymills 0:ff9ebe0cf0e9 2520 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2521 data_length -= sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2522
ashleymills 0:ff9ebe0cf0e9 2523 if (data_length < dtls_uint8_to_int(data)) {
ashleymills 0:ff9ebe0cf0e9 2524 DBG("signature length wrong");
ashleymills 0:ff9ebe0cf0e9 2525 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 2526 }
ashleymills 0:ff9ebe0cf0e9 2527 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2528 data_length -= sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2529
ashleymills 0:ff9ebe0cf0e9 2530 if (dtls_uint8_to_int(data) != 0x02) {
ashleymills 0:ff9ebe0cf0e9 2531 DBG("wrong ASN.1 struct, expected Integer");
ashleymills 0:ff9ebe0cf0e9 2532 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 2533 }
ashleymills 0:ff9ebe0cf0e9 2534 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2535 data_length -= sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2536
ashleymills 0:ff9ebe0cf0e9 2537 i = dtls_uint8_to_int(data);
ashleymills 0:ff9ebe0cf0e9 2538 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2539 data_length -= sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2540
ashleymills 0:ff9ebe0cf0e9 2541 /* Sometimes these values have a leeding 0 byte */
ashleymills 0:ff9ebe0cf0e9 2542 result_r = data + i - DTLS_EC_KEY_SIZE;
ashleymills 0:ff9ebe0cf0e9 2543
ashleymills 0:ff9ebe0cf0e9 2544 data += i;
ashleymills 0:ff9ebe0cf0e9 2545 data_length -= i;
ashleymills 0:ff9ebe0cf0e9 2546
ashleymills 0:ff9ebe0cf0e9 2547 if (dtls_uint8_to_int(data) != 0x02) {
ashleymills 0:ff9ebe0cf0e9 2548 DBG("wrong ASN.1 struct, expected Integer");
ashleymills 0:ff9ebe0cf0e9 2549 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 2550 }
ashleymills 0:ff9ebe0cf0e9 2551 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2552 data_length -= sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2553
ashleymills 0:ff9ebe0cf0e9 2554 i = dtls_uint8_to_int(data);
ashleymills 0:ff9ebe0cf0e9 2555 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2556 data_length -= sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2557
ashleymills 0:ff9ebe0cf0e9 2558 /* Sometimes these values have a leeding 0 byte */
ashleymills 0:ff9ebe0cf0e9 2559 result_s = data + i - DTLS_EC_KEY_SIZE;
ashleymills 0:ff9ebe0cf0e9 2560
ashleymills 0:ff9ebe0cf0e9 2561 data += i;
ashleymills 0:ff9ebe0cf0e9 2562 data_length -= i;
ashleymills 0:ff9ebe0cf0e9 2563
ashleymills 0:ff9ebe0cf0e9 2564 i = dtls_ecdsa_verify_sig(config->keyx.ecdsa.other_pub_x, config->keyx.ecdsa.other_pub_y,
ashleymills 0:ff9ebe0cf0e9 2565 sizeof(config->keyx.ecdsa.other_pub_x),
ashleymills 0:ff9ebe0cf0e9 2566 config->tmp.random.client, DTLS_RANDOM_LENGTH,
ashleymills 0:ff9ebe0cf0e9 2567 config->tmp.random.server, DTLS_RANDOM_LENGTH,
ashleymills 0:ff9ebe0cf0e9 2568 key_params,
ashleymills 0:ff9ebe0cf0e9 2569 1 + 2 + 1 + 1 + (2 * DTLS_EC_KEY_SIZE),
ashleymills 0:ff9ebe0cf0e9 2570 result_r, result_s);
ashleymills 0:ff9ebe0cf0e9 2571
ashleymills 0:ff9ebe0cf0e9 2572 if (i < 0) {
ashleymills 0:ff9ebe0cf0e9 2573 DBG("wrong signature");
ashleymills 0:ff9ebe0cf0e9 2574 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 2575 }
ashleymills 0:ff9ebe0cf0e9 2576 return 0;
ashleymills 0:ff9ebe0cf0e9 2577 }
ashleymills 0:ff9ebe0cf0e9 2578
ashleymills 0:ff9ebe0cf0e9 2579 static int
ashleymills 0:ff9ebe0cf0e9 2580 check_server_key_exchange_psk(dtls_context_t *ctx,
ashleymills 0:ff9ebe0cf0e9 2581 dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 2582 uint8 *data, size_t data_length)
ashleymills 0:ff9ebe0cf0e9 2583 {
ashleymills 0:ff9ebe0cf0e9 2584 DBG("check_server_key_exchange_psk");
ashleymills 0:ff9ebe0cf0e9 2585 dtls_handshake_parameters_t *config = &peer->handshake_params;
ashleymills 0:ff9ebe0cf0e9 2586 int len;
ashleymills 0:ff9ebe0cf0e9 2587
ashleymills 0:ff9ebe0cf0e9 2588 update_hs_hash(peer, data, data_length);
ashleymills 0:ff9ebe0cf0e9 2589
ashleymills 0:ff9ebe0cf0e9 2590 assert(config->cipher == TLS_PSK_WITH_AES_128_CCM_8);
ashleymills 0:ff9ebe0cf0e9 2591
ashleymills 0:ff9ebe0cf0e9 2592 data += DTLS_HS_LENGTH;
ashleymills 0:ff9ebe0cf0e9 2593
ashleymills 0:ff9ebe0cf0e9 2594 if (data_length < DTLS_HS_LENGTH + DTLS_SKEXECPSK_LENGTH_MIN) {
ashleymills 0:ff9ebe0cf0e9 2595 DBG("the package length does not match the expected");
ashleymills 0:ff9ebe0cf0e9 2596 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 2597 }
ashleymills 0:ff9ebe0cf0e9 2598
ashleymills 0:ff9ebe0cf0e9 2599 len = dtls_uint16_to_int(data);
ashleymills 0:ff9ebe0cf0e9 2600 data += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 2601
ashleymills 0:ff9ebe0cf0e9 2602 if (len != data_length - DTLS_HS_LENGTH - sizeof(uint16)) {
ashleymills 0:ff9ebe0cf0e9 2603 WARN("the length of the server identity hint is worng");
ashleymills 0:ff9ebe0cf0e9 2604 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 2605 }
ashleymills 0:ff9ebe0cf0e9 2606
ashleymills 0:ff9ebe0cf0e9 2607 if (len > DTLS_PSK_MAX_CLIENT_IDENTITY_LEN) {
ashleymills 0:ff9ebe0cf0e9 2608 WARN("please use a smaller server identity hint");
ashleymills 0:ff9ebe0cf0e9 2609 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
ashleymills 0:ff9ebe0cf0e9 2610 }
ashleymills 0:ff9ebe0cf0e9 2611
ashleymills 0:ff9ebe0cf0e9 2612 config->keyx.psk.id_length = len;
ashleymills 0:ff9ebe0cf0e9 2613 memcpy(config->keyx.psk.identity, data, len);
ashleymills 0:ff9ebe0cf0e9 2614 return 0;
ashleymills 0:ff9ebe0cf0e9 2615 }
ashleymills 0:ff9ebe0cf0e9 2616
ashleymills 0:ff9ebe0cf0e9 2617 static int
ashleymills 0:ff9ebe0cf0e9 2618 check_certificate_request(dtls_context_t *ctx,
ashleymills 0:ff9ebe0cf0e9 2619 dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 2620 uint8 *data, size_t data_length)
ashleymills 0:ff9ebe0cf0e9 2621 {
ashleymills 0:ff9ebe0cf0e9 2622 DBG("check_certificate_request");
ashleymills 0:ff9ebe0cf0e9 2623 int i;
ashleymills 0:ff9ebe0cf0e9 2624 int auth_alg;
ashleymills 0:ff9ebe0cf0e9 2625 int sig_alg;
ashleymills 0:ff9ebe0cf0e9 2626 int hash_alg;
ashleymills 0:ff9ebe0cf0e9 2627
ashleymills 0:ff9ebe0cf0e9 2628 update_hs_hash(peer, data, data_length);
ashleymills 0:ff9ebe0cf0e9 2629
ashleymills 0:ff9ebe0cf0e9 2630 assert(peer->handshake_params.cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
ashleymills 0:ff9ebe0cf0e9 2631
ashleymills 0:ff9ebe0cf0e9 2632 data += DTLS_HS_LENGTH;
ashleymills 0:ff9ebe0cf0e9 2633
ashleymills 0:ff9ebe0cf0e9 2634 if (data_length < DTLS_HS_LENGTH + 5) {
ashleymills 0:ff9ebe0cf0e9 2635 DBG("the package length does not match the expected");
ashleymills 0:ff9ebe0cf0e9 2636 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 2637 }
ashleymills 0:ff9ebe0cf0e9 2638
ashleymills 0:ff9ebe0cf0e9 2639 i = dtls_uint8_to_int(data);
ashleymills 0:ff9ebe0cf0e9 2640 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2641 if (i + 1 > data_length) {
ashleymills 0:ff9ebe0cf0e9 2642 DBG("the cerfificate types are too long");
ashleymills 0:ff9ebe0cf0e9 2643 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 2644 }
ashleymills 0:ff9ebe0cf0e9 2645
ashleymills 0:ff9ebe0cf0e9 2646 auth_alg = 0;
ashleymills 0:ff9ebe0cf0e9 2647 for (; i > 0 ; i -= sizeof(uint8)) {
ashleymills 0:ff9ebe0cf0e9 2648 if (dtls_uint8_to_int(data) == 64 && auth_alg == 0)
ashleymills 0:ff9ebe0cf0e9 2649 auth_alg = dtls_uint8_to_int(data);
ashleymills 0:ff9ebe0cf0e9 2650 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2651 }
ashleymills 0:ff9ebe0cf0e9 2652
ashleymills 0:ff9ebe0cf0e9 2653 if (auth_alg != 64) {
ashleymills 0:ff9ebe0cf0e9 2654 DBG("the request authentication algorithem is not supproted");
ashleymills 0:ff9ebe0cf0e9 2655 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 2656 }
ashleymills 0:ff9ebe0cf0e9 2657
ashleymills 0:ff9ebe0cf0e9 2658 i = dtls_uint16_to_int(data);
ashleymills 0:ff9ebe0cf0e9 2659 data += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 2660 if (i + 1 > data_length) {
ashleymills 0:ff9ebe0cf0e9 2661 DBG("the signature and hash algorithm list is too long");
ashleymills 0:ff9ebe0cf0e9 2662 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 2663 }
ashleymills 0:ff9ebe0cf0e9 2664
ashleymills 0:ff9ebe0cf0e9 2665 hash_alg = 0;
ashleymills 0:ff9ebe0cf0e9 2666 sig_alg = 0;
ashleymills 0:ff9ebe0cf0e9 2667 for (; i > 0 ; i -= sizeof(uint16)) {
ashleymills 0:ff9ebe0cf0e9 2668 int current_hash_alg;
ashleymills 0:ff9ebe0cf0e9 2669 int current_sig_alg;
ashleymills 0:ff9ebe0cf0e9 2670
ashleymills 0:ff9ebe0cf0e9 2671 current_hash_alg = dtls_uint8_to_int(data);
ashleymills 0:ff9ebe0cf0e9 2672 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2673 current_sig_alg = dtls_uint8_to_int(data);
ashleymills 0:ff9ebe0cf0e9 2674 data += sizeof(uint8);
ashleymills 0:ff9ebe0cf0e9 2675
ashleymills 0:ff9ebe0cf0e9 2676 if (current_hash_alg == 4 && hash_alg == 0 &&
ashleymills 0:ff9ebe0cf0e9 2677 current_sig_alg == 3 && sig_alg == 0) {
ashleymills 0:ff9ebe0cf0e9 2678 hash_alg = current_hash_alg;
ashleymills 0:ff9ebe0cf0e9 2679 sig_alg = current_sig_alg;
ashleymills 0:ff9ebe0cf0e9 2680 }
ashleymills 0:ff9ebe0cf0e9 2681 }
ashleymills 0:ff9ebe0cf0e9 2682
ashleymills 0:ff9ebe0cf0e9 2683 if (hash_alg != 4 || sig_alg != 3) {
ashleymills 0:ff9ebe0cf0e9 2684 DBG("no supported hash and signature algorithem");
ashleymills 0:ff9ebe0cf0e9 2685 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 2686 }
ashleymills 0:ff9ebe0cf0e9 2687
ashleymills 0:ff9ebe0cf0e9 2688 /* common names are ignored */
ashleymills 0:ff9ebe0cf0e9 2689
ashleymills 0:ff9ebe0cf0e9 2690 peer->handshake_params.do_client_auth = 1;
ashleymills 0:ff9ebe0cf0e9 2691 return 0;
ashleymills 0:ff9ebe0cf0e9 2692 }
ashleymills 0:ff9ebe0cf0e9 2693
ashleymills 0:ff9ebe0cf0e9 2694 static int
ashleymills 0:ff9ebe0cf0e9 2695 check_server_hellodone(dtls_context_t *ctx,
ashleymills 0:ff9ebe0cf0e9 2696 dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 2697 uint8 *data, size_t data_length)
ashleymills 0:ff9ebe0cf0e9 2698 {
ashleymills 0:ff9ebe0cf0e9 2699 int res;
ashleymills 0:ff9ebe0cf0e9 2700 const dtls_ecdsa_key_t *ecdsa_key;
ashleymills 0:ff9ebe0cf0e9 2701 dtls_handshake_parameters_t *handshake = &peer->handshake_params;
ashleymills 0:ff9ebe0cf0e9 2702 dtls_security_parameters_t *security = &peer->security_params;
ashleymills 0:ff9ebe0cf0e9 2703 DBG("check_server_hellodone");
ashleymills 0:ff9ebe0cf0e9 2704 /* calculate master key, send CCS */
ashleymills 0:ff9ebe0cf0e9 2705
ashleymills 0:ff9ebe0cf0e9 2706 update_hs_hash(peer, data, data_length);
ashleymills 0:ff9ebe0cf0e9 2707
ashleymills 0:ff9ebe0cf0e9 2708 if (handshake->do_client_auth) {
ashleymills 0:ff9ebe0cf0e9 2709
ashleymills 0:ff9ebe0cf0e9 2710 res = CALL(ctx, get_ecdsa_key, &peer->session, &ecdsa_key);
ashleymills 0:ff9ebe0cf0e9 2711 if (res < 0) {
ashleymills 0:ff9ebe0cf0e9 2712 DBG("no ecdsa certificate to send in certificate");
ashleymills 0:ff9ebe0cf0e9 2713 return res;
ashleymills 0:ff9ebe0cf0e9 2714 }
ashleymills 0:ff9ebe0cf0e9 2715
ashleymills 0:ff9ebe0cf0e9 2716 res = dtls_send_certificate_ecdsa(ctx, peer, ecdsa_key);
ashleymills 0:ff9ebe0cf0e9 2717
ashleymills 0:ff9ebe0cf0e9 2718 if (res < 0) {
ashleymills 0:ff9ebe0cf0e9 2719 DBG("dtls_server_hello: cannot prepare Certificate record");
ashleymills 0:ff9ebe0cf0e9 2720 return res;
ashleymills 0:ff9ebe0cf0e9 2721 }
ashleymills 0:ff9ebe0cf0e9 2722 }
ashleymills 0:ff9ebe0cf0e9 2723
ashleymills 0:ff9ebe0cf0e9 2724 /* send ClientKeyExchange */
ashleymills 0:ff9ebe0cf0e9 2725 res = dtls_send_client_key_exchange(ctx, peer);
ashleymills 0:ff9ebe0cf0e9 2726
ashleymills 0:ff9ebe0cf0e9 2727 if (res < 0) {
ashleymills 0:ff9ebe0cf0e9 2728 DBG("cannot send KeyExchange message");
ashleymills 0:ff9ebe0cf0e9 2729 return res;
ashleymills 0:ff9ebe0cf0e9 2730 }
ashleymills 0:ff9ebe0cf0e9 2731
ashleymills 0:ff9ebe0cf0e9 2732 if (handshake->do_client_auth) {
ashleymills 0:ff9ebe0cf0e9 2733
ashleymills 0:ff9ebe0cf0e9 2734 res = dtls_send_certificate_verify_ecdh(ctx, peer, ecdsa_key);
ashleymills 0:ff9ebe0cf0e9 2735
ashleymills 0:ff9ebe0cf0e9 2736 if (res < 0) {
ashleymills 0:ff9ebe0cf0e9 2737 DBG("dtls_server_hello: cannot prepare Certificate record");
ashleymills 0:ff9ebe0cf0e9 2738 return res;
ashleymills 0:ff9ebe0cf0e9 2739 }
ashleymills 0:ff9ebe0cf0e9 2740 }
ashleymills 0:ff9ebe0cf0e9 2741
ashleymills 0:ff9ebe0cf0e9 2742 /* and switch cipher suite */
ashleymills 0:ff9ebe0cf0e9 2743 res = dtls_send_ccs(ctx, peer);
ashleymills 0:ff9ebe0cf0e9 2744 if (res < 0) {
ashleymills 0:ff9ebe0cf0e9 2745 DBG("cannot send CCS message");
ashleymills 0:ff9ebe0cf0e9 2746 return res;
ashleymills 0:ff9ebe0cf0e9 2747 }
ashleymills 0:ff9ebe0cf0e9 2748
ashleymills 0:ff9ebe0cf0e9 2749 res = calculate_key_block(ctx, handshake, security,
ashleymills 0:ff9ebe0cf0e9 2750 &peer->session);
ashleymills 0:ff9ebe0cf0e9 2751 if (res < 0) {
ashleymills 0:ff9ebe0cf0e9 2752 return res;
ashleymills 0:ff9ebe0cf0e9 2753 }
ashleymills 0:ff9ebe0cf0e9 2754
ashleymills 0:ff9ebe0cf0e9 2755 res = init_cipher(handshake, security, peer->role);
ashleymills 0:ff9ebe0cf0e9 2756 if (res < 0) {
ashleymills 0:ff9ebe0cf0e9 2757 return res;
ashleymills 0:ff9ebe0cf0e9 2758 }
ashleymills 0:ff9ebe0cf0e9 2759
ashleymills 0:ff9ebe0cf0e9 2760 inc_uint(uint16, peer->epoch);
ashleymills 0:ff9ebe0cf0e9 2761 memset(peer->rseq, 0, sizeof(peer->rseq));
ashleymills 0:ff9ebe0cf0e9 2762
ashleymills 0:ff9ebe0cf0e9 2763 dtls_debug_keyblock(security);
ashleymills 0:ff9ebe0cf0e9 2764
ashleymills 0:ff9ebe0cf0e9 2765 /* Client Finished */
ashleymills 0:ff9ebe0cf0e9 2766 DBG("send Finished");
ashleymills 0:ff9ebe0cf0e9 2767 return dtls_send_finished(ctx, peer, PRF_LABEL(client), PRF_LABEL_SIZE(client));
ashleymills 0:ff9ebe0cf0e9 2768 }
ashleymills 0:ff9ebe0cf0e9 2769
ashleymills 0:ff9ebe0cf0e9 2770 static int
ashleymills 0:ff9ebe0cf0e9 2771 decrypt_verify(dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 2772 uint8 *packet, size_t length,
ashleymills 0:ff9ebe0cf0e9 2773 uint8 **cleartext, size_t *clen) {
ashleymills 0:ff9ebe0cf0e9 2774 int ok = 0;
ashleymills 0:ff9ebe0cf0e9 2775 dtls_security_parameters_t *security = &peer->security_params;
ashleymills 0:ff9ebe0cf0e9 2776
ashleymills 0:ff9ebe0cf0e9 2777 *cleartext = (uint8 *)packet + sizeof(dtls_record_header_t);
ashleymills 0:ff9ebe0cf0e9 2778 *clen = length - sizeof(dtls_record_header_t);
ashleymills 0:ff9ebe0cf0e9 2779
ashleymills 0:ff9ebe0cf0e9 2780 if (security->cipher == TLS_NULL_WITH_NULL_NULL) {
ashleymills 0:ff9ebe0cf0e9 2781 /* no cipher suite selected */
ashleymills 0:ff9ebe0cf0e9 2782 return 1;
ashleymills 0:ff9ebe0cf0e9 2783 } else { /* TLS_PSK_WITH_AES_128_CCM_8 */
ashleymills 0:ff9ebe0cf0e9 2784 dtls_cipher_context_t *cipher_context;
ashleymills 0:ff9ebe0cf0e9 2785 /**
ashleymills 0:ff9ebe0cf0e9 2786 * length of additional_data for the AEAD cipher which consists of
ashleymills 0:ff9ebe0cf0e9 2787 * seq_num(2+6) + type(1) + version(2) + length(2)
ashleymills 0:ff9ebe0cf0e9 2788 */
ashleymills 0:ff9ebe0cf0e9 2789 #define A_DATA_LEN 13
ashleymills 0:ff9ebe0cf0e9 2790 unsigned char nonce[DTLS_CCM_BLOCKSIZE];
ashleymills 0:ff9ebe0cf0e9 2791 unsigned char A_DATA[A_DATA_LEN];
ashleymills 0:ff9ebe0cf0e9 2792 long int len;
ashleymills 0:ff9ebe0cf0e9 2793
ashleymills 0:ff9ebe0cf0e9 2794
ashleymills 0:ff9ebe0cf0e9 2795 if (*clen < 16) /* need at least IV and MAC */
ashleymills 0:ff9ebe0cf0e9 2796 return -1;
ashleymills 0:ff9ebe0cf0e9 2797
ashleymills 0:ff9ebe0cf0e9 2798 memset(nonce, 0, DTLS_CCM_BLOCKSIZE);
ashleymills 0:ff9ebe0cf0e9 2799 memcpy(nonce, dtls_kb_remote_iv(security, peer->role),
ashleymills 0:ff9ebe0cf0e9 2800 dtls_kb_iv_size(security, peer->role));
ashleymills 0:ff9ebe0cf0e9 2801
ashleymills 0:ff9ebe0cf0e9 2802 /* read epoch and seq_num from message */
ashleymills 0:ff9ebe0cf0e9 2803 memcpy(nonce + dtls_kb_iv_size(security, peer->role), *cleartext, 8);
ashleymills 0:ff9ebe0cf0e9 2804 *cleartext += 8;
ashleymills 0:ff9ebe0cf0e9 2805 *clen -= 8;
ashleymills 0:ff9ebe0cf0e9 2806
ashleymills 0:ff9ebe0cf0e9 2807 cipher_context = security->read_cipher;
ashleymills 0:ff9ebe0cf0e9 2808
ashleymills 0:ff9ebe0cf0e9 2809 if (!cipher_context) {
ashleymills 0:ff9ebe0cf0e9 2810 WARN("no read_cipher available!");
ashleymills 0:ff9ebe0cf0e9 2811 return 0;
ashleymills 0:ff9ebe0cf0e9 2812 }
ashleymills 0:ff9ebe0cf0e9 2813
ashleymills 0:ff9ebe0cf0e9 2814 dtls_dsrv_hexdump_log(LOG_DEBUG, "nonce", nonce, DTLS_CCM_BLOCKSIZE, 0);
ashleymills 0:ff9ebe0cf0e9 2815 dtls_dsrv_hexdump_log(LOG_DEBUG, "key",
ashleymills 0:ff9ebe0cf0e9 2816 dtls_kb_remote_write_key(security, peer->role),
ashleymills 0:ff9ebe0cf0e9 2817 dtls_kb_key_size(security, peer->role), 0);
ashleymills 0:ff9ebe0cf0e9 2818 dtls_dsrv_hexdump_log(LOG_DEBUG, "ciphertext", *cleartext, *clen, 0);
ashleymills 0:ff9ebe0cf0e9 2819
ashleymills 0:ff9ebe0cf0e9 2820 /* re-use N to create additional data according to RFC 5246, Section 6.2.3.3:
ashleymills 0:ff9ebe0cf0e9 2821 *
ashleymills 0:ff9ebe0cf0e9 2822 * additional_data = seq_num + TLSCompressed.type +
ashleymills 0:ff9ebe0cf0e9 2823 * TLSCompressed.version + TLSCompressed.length;
ashleymills 0:ff9ebe0cf0e9 2824 */
ashleymills 0:ff9ebe0cf0e9 2825 memcpy(A_DATA, &DTLS_RECORD_HEADER(packet)->epoch, 8); /* epoch and seq_num */
ashleymills 0:ff9ebe0cf0e9 2826 memcpy(A_DATA + 8, &DTLS_RECORD_HEADER(packet)->content_type, 3); /* type and version */
ashleymills 0:ff9ebe0cf0e9 2827 dtls_int_to_uint16(A_DATA + 11, *clen - 8); /* length without nonce_explicit */
ashleymills 0:ff9ebe0cf0e9 2828
ashleymills 0:ff9ebe0cf0e9 2829 len = dtls_decrypt(cipher_context, *cleartext, *clen, *cleartext, nonce,
ashleymills 0:ff9ebe0cf0e9 2830 A_DATA, A_DATA_LEN);
ashleymills 0:ff9ebe0cf0e9 2831
ashleymills 0:ff9ebe0cf0e9 2832 ok = len >= 0;
ashleymills 0:ff9ebe0cf0e9 2833 if (!ok)
ashleymills 0:ff9ebe0cf0e9 2834 WARN("decryption failed");
ashleymills 0:ff9ebe0cf0e9 2835 else {
ashleymills 0:ff9ebe0cf0e9 2836 #ifndef NDEBUG
ashleymills 0:ff9ebe0cf0e9 2837 printf("decrypt_verify(): found %ld bytes cleartext", len);
ashleymills 0:ff9ebe0cf0e9 2838 #endif
ashleymills 0:ff9ebe0cf0e9 2839 *clen = len;
ashleymills 0:ff9ebe0cf0e9 2840 }
ashleymills 0:ff9ebe0cf0e9 2841 dtls_dsrv_hexdump_log(LOG_DEBUG, "cleartext", *cleartext, *clen, 0);
ashleymills 0:ff9ebe0cf0e9 2842 }
ashleymills 0:ff9ebe0cf0e9 2843
ashleymills 0:ff9ebe0cf0e9 2844 return ok;
ashleymills 0:ff9ebe0cf0e9 2845 }
ashleymills 0:ff9ebe0cf0e9 2846
ashleymills 0:ff9ebe0cf0e9 2847 static int
ashleymills 0:ff9ebe0cf0e9 2848 dtls_send_hello_request(dtls_context_t *ctx, dtls_peer_t *peer)
ashleymills 0:ff9ebe0cf0e9 2849 {
ashleymills 0:ff9ebe0cf0e9 2850 return dtls_send_handshake_msg_hash(ctx, peer, &peer->session,
ashleymills 0:ff9ebe0cf0e9 2851 DTLS_HT_HELLO_REQUEST,
ashleymills 0:ff9ebe0cf0e9 2852 NULL, 0, 0);
ashleymills 0:ff9ebe0cf0e9 2853 }
ashleymills 0:ff9ebe0cf0e9 2854
ashleymills 0:ff9ebe0cf0e9 2855 int
ashleymills 0:ff9ebe0cf0e9 2856 dtls_renegotiate(dtls_context_t *ctx, const session_t *dst)
ashleymills 0:ff9ebe0cf0e9 2857 {
ashleymills 0:ff9ebe0cf0e9 2858 dtls_peer_t *peer = NULL;
ashleymills 0:ff9ebe0cf0e9 2859 int err;
ashleymills 0:ff9ebe0cf0e9 2860
ashleymills 0:ff9ebe0cf0e9 2861 peer = dtls_get_peer(ctx, dst);
ashleymills 0:ff9ebe0cf0e9 2862
ashleymills 0:ff9ebe0cf0e9 2863 if (!peer) {
ashleymills 0:ff9ebe0cf0e9 2864 return -1;
ashleymills 0:ff9ebe0cf0e9 2865 }
ashleymills 0:ff9ebe0cf0e9 2866 if (peer->state != DTLS_STATE_CONNECTED)
ashleymills 0:ff9ebe0cf0e9 2867 return -1;
ashleymills 0:ff9ebe0cf0e9 2868
ashleymills 0:ff9ebe0cf0e9 2869 if (peer->role == DTLS_CLIENT) {
ashleymills 0:ff9ebe0cf0e9 2870 /* send ClientHello with empty Cookie */
ashleymills 0:ff9ebe0cf0e9 2871 err = dtls_send_client_hello(ctx, peer, NULL, 0);
ashleymills 0:ff9ebe0cf0e9 2872 if (err < 0)
ashleymills 0:ff9ebe0cf0e9 2873 WARN("cannot send ClientHello");
ashleymills 0:ff9ebe0cf0e9 2874 else
ashleymills 0:ff9ebe0cf0e9 2875 peer->state = DTLS_STATE_CLIENTHELLO;
ashleymills 0:ff9ebe0cf0e9 2876 return err;
ashleymills 0:ff9ebe0cf0e9 2877 } else if (peer->role == DTLS_SERVER) {
ashleymills 0:ff9ebe0cf0e9 2878 return dtls_send_hello_request(ctx, peer);
ashleymills 0:ff9ebe0cf0e9 2879 }
ashleymills 0:ff9ebe0cf0e9 2880
ashleymills 0:ff9ebe0cf0e9 2881 return -1;
ashleymills 0:ff9ebe0cf0e9 2882 }
ashleymills 0:ff9ebe0cf0e9 2883
ashleymills 0:ff9ebe0cf0e9 2884 static int
ashleymills 0:ff9ebe0cf0e9 2885 handle_handshake(dtls_context_t *ctx, dtls_peer_t *peer, session_t *session,
ashleymills 0:ff9ebe0cf0e9 2886 const dtls_peer_type role, const dtls_state_t state,
ashleymills 0:ff9ebe0cf0e9 2887 uint8 *record_header, uint8 *data, size_t data_length) {
ashleymills 0:ff9ebe0cf0e9 2888
ashleymills 0:ff9ebe0cf0e9 2889 int err = 0;
ashleymills 0:ff9ebe0cf0e9 2890
ashleymills 0:ff9ebe0cf0e9 2891 if (data_length < DTLS_HS_LENGTH) {
ashleymills 0:ff9ebe0cf0e9 2892 WARN("handshake message too short");
ashleymills 0:ff9ebe0cf0e9 2893 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 2894 }
ashleymills 0:ff9ebe0cf0e9 2895
ashleymills 0:ff9ebe0cf0e9 2896 if (!peer && data[0] != DTLS_HT_CLIENT_HELLO) {
ashleymills 0:ff9ebe0cf0e9 2897 WARN("If there is no peer only ClientHello is allowed");
ashleymills 0:ff9ebe0cf0e9 2898 return dtls_alert_fatal_create(DTLS_ALERT_HANDSHAKE_FAILURE);
ashleymills 0:ff9ebe0cf0e9 2899 }
ashleymills 0:ff9ebe0cf0e9 2900 /* The following switch construct handles the given message with
ashleymills 0:ff9ebe0cf0e9 2901 * respect to the current internal state for this peer. In case of
ashleymills 0:ff9ebe0cf0e9 2902 * error, it is left with return 0. */
ashleymills 0:ff9ebe0cf0e9 2903
ashleymills 0:ff9ebe0cf0e9 2904 switch (data[0]) {
ashleymills 0:ff9ebe0cf0e9 2905
ashleymills 0:ff9ebe0cf0e9 2906 /************************************************************************
ashleymills 0:ff9ebe0cf0e9 2907 * Client states
ashleymills 0:ff9ebe0cf0e9 2908 ************************************************************************/
ashleymills 0:ff9ebe0cf0e9 2909 case DTLS_HT_HELLO_VERIFY_REQUEST:
ashleymills 0:ff9ebe0cf0e9 2910
ashleymills 0:ff9ebe0cf0e9 2911 DBG("DTLS_HT_HELLO_VERIFY_REQUEST");
ashleymills 0:ff9ebe0cf0e9 2912 if (state != DTLS_STATE_CLIENTHELLO) {
ashleymills 0:ff9ebe0cf0e9 2913 return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE);
ashleymills 0:ff9ebe0cf0e9 2914 }
ashleymills 0:ff9ebe0cf0e9 2915
ashleymills 0:ff9ebe0cf0e9 2916 err = check_server_hello_verify_request(ctx, peer, data, data_length);
ashleymills 0:ff9ebe0cf0e9 2917 if (err < 0) {
ashleymills 0:ff9ebe0cf0e9 2918 WARN("error in check_server_hello_verify_request err: %i", err);
ashleymills 0:ff9ebe0cf0e9 2919 return err;
ashleymills 0:ff9ebe0cf0e9 2920 }
ashleymills 0:ff9ebe0cf0e9 2921
ashleymills 0:ff9ebe0cf0e9 2922 break;
ashleymills 0:ff9ebe0cf0e9 2923 case DTLS_HT_SERVER_HELLO:
ashleymills 0:ff9ebe0cf0e9 2924
ashleymills 0:ff9ebe0cf0e9 2925 DBG("DTLS_HT_SERVER_HELLO");
ashleymills 0:ff9ebe0cf0e9 2926 if (state != DTLS_STATE_CLIENTHELLO) {
ashleymills 0:ff9ebe0cf0e9 2927 return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE);
ashleymills 0:ff9ebe0cf0e9 2928 }
ashleymills 0:ff9ebe0cf0e9 2929
ashleymills 0:ff9ebe0cf0e9 2930 err = check_server_hello(ctx, peer, data, data_length);
ashleymills 0:ff9ebe0cf0e9 2931 if (err < 0) {
ashleymills 0:ff9ebe0cf0e9 2932 WARN("error in check_server_hello err: %i", err);
ashleymills 0:ff9ebe0cf0e9 2933 return err;
ashleymills 0:ff9ebe0cf0e9 2934 }
ashleymills 0:ff9ebe0cf0e9 2935 if (peer->handshake_params.cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8)
ashleymills 0:ff9ebe0cf0e9 2936 peer->state = DTLS_STATE_WAIT_SERVERCERTIFICATE;
ashleymills 0:ff9ebe0cf0e9 2937 else
ashleymills 0:ff9ebe0cf0e9 2938 peer->state = DTLS_STATE_WAIT_SERVERHELLODONE;
ashleymills 0:ff9ebe0cf0e9 2939 /* update_hs_hash(peer, data, data_length); */
ashleymills 0:ff9ebe0cf0e9 2940
ashleymills 0:ff9ebe0cf0e9 2941 break;
ashleymills 0:ff9ebe0cf0e9 2942
ashleymills 0:ff9ebe0cf0e9 2943 case DTLS_HT_CERTIFICATE:
ashleymills 0:ff9ebe0cf0e9 2944 DBG("DTLS_HT_CERTIFICATE");
ashleymills 0:ff9ebe0cf0e9 2945
ashleymills 0:ff9ebe0cf0e9 2946 if ((role == DTLS_CLIENT && state != DTLS_STATE_WAIT_SERVERCERTIFICATE) ||
ashleymills 0:ff9ebe0cf0e9 2947 (role == DTLS_SERVER && state != DTLS_STATE_WAIT_CLIENTCERTIFICATE)) {
ashleymills 0:ff9ebe0cf0e9 2948 return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE);
ashleymills 0:ff9ebe0cf0e9 2949 }
ashleymills 0:ff9ebe0cf0e9 2950 err = check_server_certificate(ctx, peer, data, data_length);
ashleymills 0:ff9ebe0cf0e9 2951 if (err < 0) {
ashleymills 0:ff9ebe0cf0e9 2952 WARN("error in check_server_certificate err: %i", err);
ashleymills 0:ff9ebe0cf0e9 2953 return err;
ashleymills 0:ff9ebe0cf0e9 2954 }
ashleymills 0:ff9ebe0cf0e9 2955 if (role == DTLS_CLIENT) {
ashleymills 0:ff9ebe0cf0e9 2956 peer->state = DTLS_STATE_WAIT_SERVERKEYEXCHANGE;
ashleymills 0:ff9ebe0cf0e9 2957 } else if (role == DTLS_SERVER){
ashleymills 0:ff9ebe0cf0e9 2958 peer->state = DTLS_STATE_WAIT_CLIENTKEYEXCHANGE;
ashleymills 0:ff9ebe0cf0e9 2959 }
ashleymills 0:ff9ebe0cf0e9 2960 /* update_hs_hash(peer, data, data_length); */
ashleymills 0:ff9ebe0cf0e9 2961
ashleymills 0:ff9ebe0cf0e9 2962 break;
ashleymills 0:ff9ebe0cf0e9 2963
ashleymills 0:ff9ebe0cf0e9 2964 case DTLS_HT_SERVER_KEY_EXCHANGE:
ashleymills 0:ff9ebe0cf0e9 2965
ashleymills 0:ff9ebe0cf0e9 2966 DBG("DTLS_HT_SERVER_KEY_EXCHANGE");
ashleymills 0:ff9ebe0cf0e9 2967
ashleymills 0:ff9ebe0cf0e9 2968 if (peer->handshake_params.cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8) {
ashleymills 0:ff9ebe0cf0e9 2969 DBG("TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8");
ashleymills 0:ff9ebe0cf0e9 2970 if (state != DTLS_STATE_WAIT_SERVERKEYEXCHANGE) {
ashleymills 0:ff9ebe0cf0e9 2971 return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE);
ashleymills 0:ff9ebe0cf0e9 2972 }
ashleymills 0:ff9ebe0cf0e9 2973 err = check_server_key_exchange_ecdsa(ctx, peer, data, data_length);
ashleymills 0:ff9ebe0cf0e9 2974 } else if (peer->handshake_params.cipher == TLS_PSK_WITH_AES_128_CCM_8) {
ashleymills 0:ff9ebe0cf0e9 2975 DBG("TLS_PSK_WITH_AES_128_CCM_8");
ashleymills 0:ff9ebe0cf0e9 2976 if (state != DTLS_STATE_WAIT_SERVERHELLODONE) {
ashleymills 0:ff9ebe0cf0e9 2977 return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE);
ashleymills 0:ff9ebe0cf0e9 2978 }
ashleymills 0:ff9ebe0cf0e9 2979 err = check_server_key_exchange_psk(ctx, peer, data, data_length);
ashleymills 0:ff9ebe0cf0e9 2980 } else {
ashleymills 0:ff9ebe0cf0e9 2981 assert(0);
ashleymills 0:ff9ebe0cf0e9 2982 }
ashleymills 0:ff9ebe0cf0e9 2983
ashleymills 0:ff9ebe0cf0e9 2984 if (err < 0) {
ashleymills 0:ff9ebe0cf0e9 2985 WARN("error in check_server_key_exchange err: %i", err);
ashleymills 0:ff9ebe0cf0e9 2986 return err;
ashleymills 0:ff9ebe0cf0e9 2987 }
ashleymills 0:ff9ebe0cf0e9 2988 peer->state = DTLS_STATE_WAIT_SERVERHELLODONE;
ashleymills 0:ff9ebe0cf0e9 2989 /* update_hs_hash(peer, data, data_length); */
ashleymills 0:ff9ebe0cf0e9 2990 DBG("Set state to DTLS_STATE_WAIT_SERVERHELLODONE");
ashleymills 0:ff9ebe0cf0e9 2991 break;
ashleymills 0:ff9ebe0cf0e9 2992
ashleymills 0:ff9ebe0cf0e9 2993 case DTLS_HT_SERVER_HELLO_DONE:
ashleymills 0:ff9ebe0cf0e9 2994
ashleymills 0:ff9ebe0cf0e9 2995 DBG("DTLS_HT_SERVER_HELLO_DONE");
ashleymills 0:ff9ebe0cf0e9 2996 if (state != DTLS_STATE_WAIT_SERVERHELLODONE) {
ashleymills 0:ff9ebe0cf0e9 2997 return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE);
ashleymills 0:ff9ebe0cf0e9 2998 }
ashleymills 0:ff9ebe0cf0e9 2999
ashleymills 0:ff9ebe0cf0e9 3000 err = check_server_hellodone(ctx, peer, data, data_length);
ashleymills 0:ff9ebe0cf0e9 3001 if (err < 0) {
ashleymills 0:ff9ebe0cf0e9 3002 WARN("error in check_server_hellodone err: %i", err);
ashleymills 0:ff9ebe0cf0e9 3003 return err;
ashleymills 0:ff9ebe0cf0e9 3004 }
ashleymills 0:ff9ebe0cf0e9 3005 peer->state = DTLS_STATE_WAIT_SERVERFINISHED;
ashleymills 0:ff9ebe0cf0e9 3006 /* update_hs_hash(peer, data, data_length); */
ashleymills 0:ff9ebe0cf0e9 3007
ashleymills 0:ff9ebe0cf0e9 3008 break;
ashleymills 0:ff9ebe0cf0e9 3009
ashleymills 0:ff9ebe0cf0e9 3010 case DTLS_HT_CERTIFICATE_REQUEST:
ashleymills 0:ff9ebe0cf0e9 3011
ashleymills 0:ff9ebe0cf0e9 3012 DBG("DTLS_HT_CERTIFICATE_REQUEST");
ashleymills 0:ff9ebe0cf0e9 3013 if (state != DTLS_STATE_WAIT_SERVERHELLODONE) {
ashleymills 0:ff9ebe0cf0e9 3014 return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE);
ashleymills 0:ff9ebe0cf0e9 3015 }
ashleymills 0:ff9ebe0cf0e9 3016
ashleymills 0:ff9ebe0cf0e9 3017 err = check_certificate_request(ctx, peer, data, data_length);
ashleymills 0:ff9ebe0cf0e9 3018 if (err < 0) {
ashleymills 0:ff9ebe0cf0e9 3019 WARN("error in check_certificate_request err: %i", err);
ashleymills 0:ff9ebe0cf0e9 3020 return err;
ashleymills 0:ff9ebe0cf0e9 3021 }
ashleymills 0:ff9ebe0cf0e9 3022
ashleymills 0:ff9ebe0cf0e9 3023 break;
ashleymills 0:ff9ebe0cf0e9 3024
ashleymills 0:ff9ebe0cf0e9 3025 case DTLS_HT_FINISHED:
ashleymills 0:ff9ebe0cf0e9 3026 /* expect a Finished message from server */
ashleymills 0:ff9ebe0cf0e9 3027
ashleymills 0:ff9ebe0cf0e9 3028 DBG("DTLS_HT_FINISHED");
ashleymills 0:ff9ebe0cf0e9 3029 if ((role == DTLS_CLIENT && state != DTLS_STATE_WAIT_SERVERFINISHED) ||
ashleymills 0:ff9ebe0cf0e9 3030 (role == DTLS_SERVER && state != DTLS_STATE_WAIT_FINISHED)) {
ashleymills 0:ff9ebe0cf0e9 3031 return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE);
ashleymills 0:ff9ebe0cf0e9 3032 }
ashleymills 0:ff9ebe0cf0e9 3033
ashleymills 0:ff9ebe0cf0e9 3034 err = check_finished(ctx, peer, record_header, data, data_length);
ashleymills 0:ff9ebe0cf0e9 3035 if (err < 0) {
ashleymills 0:ff9ebe0cf0e9 3036 WARN("error in check_finished err: %i", err);
ashleymills 0:ff9ebe0cf0e9 3037 return err;
ashleymills 0:ff9ebe0cf0e9 3038 }
ashleymills 0:ff9ebe0cf0e9 3039 if (role == DTLS_SERVER) {
ashleymills 0:ff9ebe0cf0e9 3040 /* send ServerFinished */
ashleymills 0:ff9ebe0cf0e9 3041 update_hs_hash(peer, data, data_length);
ashleymills 0:ff9ebe0cf0e9 3042
ashleymills 0:ff9ebe0cf0e9 3043 if (dtls_send_finished(ctx, peer, PRF_LABEL(server),
ashleymills 0:ff9ebe0cf0e9 3044 PRF_LABEL_SIZE(server)) > 0) {
ashleymills 0:ff9ebe0cf0e9 3045 peer->state = DTLS_STATE_CONNECTED;
ashleymills 0:ff9ebe0cf0e9 3046 } else if (role == DTLS_CLIENT) {
ashleymills 0:ff9ebe0cf0e9 3047 WARN("sending server Finished failed");
ashleymills 0:ff9ebe0cf0e9 3048 }
ashleymills 0:ff9ebe0cf0e9 3049 } else {
ashleymills 0:ff9ebe0cf0e9 3050 peer->state = DTLS_STATE_CONNECTED;
ashleymills 0:ff9ebe0cf0e9 3051 }
ashleymills 0:ff9ebe0cf0e9 3052
ashleymills 0:ff9ebe0cf0e9 3053 break;
ashleymills 0:ff9ebe0cf0e9 3054
ashleymills 0:ff9ebe0cf0e9 3055 /************************************************************************
ashleymills 0:ff9ebe0cf0e9 3056 * Server states
ashleymills 0:ff9ebe0cf0e9 3057 ************************************************************************/
ashleymills 0:ff9ebe0cf0e9 3058
ashleymills 0:ff9ebe0cf0e9 3059 case DTLS_HT_CLIENT_KEY_EXCHANGE:
ashleymills 0:ff9ebe0cf0e9 3060 /* handle ClientHello, update msg and msglen and goto next if not finished */
ashleymills 0:ff9ebe0cf0e9 3061
ashleymills 0:ff9ebe0cf0e9 3062 DBG("DTLS_HT_CLIENT_KEY_EXCHANGE");
ashleymills 0:ff9ebe0cf0e9 3063
ashleymills 0:ff9ebe0cf0e9 3064 if (state != DTLS_STATE_WAIT_CLIENTKEYEXCHANGE) {
ashleymills 0:ff9ebe0cf0e9 3065 return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE);
ashleymills 0:ff9ebe0cf0e9 3066 }
ashleymills 0:ff9ebe0cf0e9 3067
ashleymills 0:ff9ebe0cf0e9 3068 err = check_client_keyexchange(ctx, &peer->handshake_params, data, data_length);
ashleymills 0:ff9ebe0cf0e9 3069 if (err < 0) {
ashleymills 0:ff9ebe0cf0e9 3070 WARN("error in check_client_keyexchange err: %i", err);
ashleymills 0:ff9ebe0cf0e9 3071 return err;
ashleymills 0:ff9ebe0cf0e9 3072 }
ashleymills 0:ff9ebe0cf0e9 3073 update_hs_hash(peer, data, data_length);
ashleymills 0:ff9ebe0cf0e9 3074
ashleymills 0:ff9ebe0cf0e9 3075 if (peer->handshake_params.cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 &&
ashleymills 0:ff9ebe0cf0e9 3076 ctx && ctx->h && ctx->h->verify_ecdsa_key)
ashleymills 0:ff9ebe0cf0e9 3077 peer->state = DTLS_STATE_WAIT_CERTIFICATEVERIFY;
ashleymills 0:ff9ebe0cf0e9 3078 else
ashleymills 0:ff9ebe0cf0e9 3079 peer->state = DTLS_STATE_WAIT_CLIENTCHANGECIPHERSPEC;
ashleymills 0:ff9ebe0cf0e9 3080 break;
ashleymills 0:ff9ebe0cf0e9 3081
ashleymills 0:ff9ebe0cf0e9 3082 case DTLS_HT_CERTIFICATE_VERIFY:
ashleymills 0:ff9ebe0cf0e9 3083
ashleymills 0:ff9ebe0cf0e9 3084 DBG("DTLS_HT_CERTIFICATE_VERIFY");
ashleymills 0:ff9ebe0cf0e9 3085 if (state != DTLS_STATE_WAIT_CERTIFICATEVERIFY) {
ashleymills 0:ff9ebe0cf0e9 3086 return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE);
ashleymills 0:ff9ebe0cf0e9 3087 }
ashleymills 0:ff9ebe0cf0e9 3088
ashleymills 0:ff9ebe0cf0e9 3089 err = check_client_certificate_verify(ctx, peer, data, data_length);
ashleymills 0:ff9ebe0cf0e9 3090 if (err < 0) {
ashleymills 0:ff9ebe0cf0e9 3091 WARN("error in check_client_certificate_verify err: %i", err);
ashleymills 0:ff9ebe0cf0e9 3092 return err;
ashleymills 0:ff9ebe0cf0e9 3093 }
ashleymills 0:ff9ebe0cf0e9 3094
ashleymills 0:ff9ebe0cf0e9 3095 update_hs_hash(peer, data, data_length);
ashleymills 0:ff9ebe0cf0e9 3096 peer->state = DTLS_STATE_WAIT_CLIENTCHANGECIPHERSPEC;
ashleymills 0:ff9ebe0cf0e9 3097 break;
ashleymills 0:ff9ebe0cf0e9 3098
ashleymills 0:ff9ebe0cf0e9 3099 case DTLS_HT_CLIENT_HELLO:
ashleymills 0:ff9ebe0cf0e9 3100 /* At this point, we have a good relationship with this peer. This
ashleymills 0:ff9ebe0cf0e9 3101 * state is left for re-negotiation of key material. */
ashleymills 0:ff9ebe0cf0e9 3102
ashleymills 0:ff9ebe0cf0e9 3103 DBG("DTLS_HT_CLIENT_HELLO");
ashleymills 0:ff9ebe0cf0e9 3104 if ((peer && state != DTLS_STATE_CONNECTED) ||
ashleymills 0:ff9ebe0cf0e9 3105 (!peer && state != DTLS_STATE_WAIT_CLIENTHELLO)) {
ashleymills 0:ff9ebe0cf0e9 3106 return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE);
ashleymills 0:ff9ebe0cf0e9 3107 }
ashleymills 0:ff9ebe0cf0e9 3108
ashleymills 0:ff9ebe0cf0e9 3109 /* When no DTLS state exists for this peer, we only allow a
ashleymills 0:ff9ebe0cf0e9 3110 Client Hello message with
ashleymills 0:ff9ebe0cf0e9 3111
ashleymills 0:ff9ebe0cf0e9 3112 a) a valid cookie, or
ashleymills 0:ff9ebe0cf0e9 3113 b) no cookie.
ashleymills 0:ff9ebe0cf0e9 3114
ashleymills 0:ff9ebe0cf0e9 3115 Anything else will be rejected. Fragementation is not allowed
ashleymills 0:ff9ebe0cf0e9 3116 here as it would require peer state as well.
ashleymills 0:ff9ebe0cf0e9 3117 */
ashleymills 0:ff9ebe0cf0e9 3118 err = dtls_verify_peer(ctx, peer, session, record_header, data,
ashleymills 0:ff9ebe0cf0e9 3119 data_length);
ashleymills 0:ff9ebe0cf0e9 3120 if (err < 0) {
ashleymills 0:ff9ebe0cf0e9 3121 WARN("error in dtls_verify_peer err: %i", err);
ashleymills 0:ff9ebe0cf0e9 3122 return err;
ashleymills 0:ff9ebe0cf0e9 3123 }
ashleymills 0:ff9ebe0cf0e9 3124
ashleymills 0:ff9ebe0cf0e9 3125 if (err > 0) {
ashleymills 0:ff9ebe0cf0e9 3126 DBG("server hello verify was sent");
ashleymills 0:ff9ebe0cf0e9 3127 return err;
ashleymills 0:ff9ebe0cf0e9 3128 }
ashleymills 0:ff9ebe0cf0e9 3129
ashleymills 0:ff9ebe0cf0e9 3130 if (!peer) {
ashleymills 0:ff9ebe0cf0e9 3131
ashleymills 0:ff9ebe0cf0e9 3132 /* msg contains a Client Hello with a valid cookie, so we can
ashleymills 0:ff9ebe0cf0e9 3133 * safely create the server state machine and continue with
ashleymills 0:ff9ebe0cf0e9 3134 * the handshake. */
ashleymills 0:ff9ebe0cf0e9 3135 peer = dtls_new_peer(session);
ashleymills 0:ff9ebe0cf0e9 3136 if (!peer) {
ashleymills 0:ff9ebe0cf0e9 3137 DBG("cannot create peer");
ashleymills 0:ff9ebe0cf0e9 3138 return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
ashleymills 0:ff9ebe0cf0e9 3139 }
ashleymills 0:ff9ebe0cf0e9 3140 peer->role = DTLS_SERVER;
ashleymills 0:ff9ebe0cf0e9 3141
ashleymills 0:ff9ebe0cf0e9 3142 /* Initialize record sequence number to 1 for new peers. The first
ashleymills 0:ff9ebe0cf0e9 3143 * record with sequence number 0 is a stateless Hello Verify Request.
ashleymills 0:ff9ebe0cf0e9 3144 */
ashleymills 0:ff9ebe0cf0e9 3145 peer->rseq[5] = 1;
ashleymills 0:ff9ebe0cf0e9 3146 dtls_add_peer(ctx, peer);
ashleymills 0:ff9ebe0cf0e9 3147 }
ashleymills 0:ff9ebe0cf0e9 3148
ashleymills 0:ff9ebe0cf0e9 3149 clear_hs_hash(peer);
ashleymills 0:ff9ebe0cf0e9 3150
ashleymills 0:ff9ebe0cf0e9 3151 /* First negotiation step: check for PSK
ashleymills 0:ff9ebe0cf0e9 3152 *
ashleymills 0:ff9ebe0cf0e9 3153 * Note that we already have checked that msg is a Handshake
ashleymills 0:ff9ebe0cf0e9 3154 * message containing a ClientHello. dtls_get_cipher() therefore
ashleymills 0:ff9ebe0cf0e9 3155 * does not check again.
ashleymills 0:ff9ebe0cf0e9 3156 */
ashleymills 0:ff9ebe0cf0e9 3157 err = dtls_update_parameters(ctx, peer, data, data_length);
ashleymills 0:ff9ebe0cf0e9 3158 if (err < 0) {
ashleymills 0:ff9ebe0cf0e9 3159
ashleymills 0:ff9ebe0cf0e9 3160 WARN("error updating security parameters");
ashleymills 0:ff9ebe0cf0e9 3161 return err;
ashleymills 0:ff9ebe0cf0e9 3162 }
ashleymills 0:ff9ebe0cf0e9 3163
ashleymills 0:ff9ebe0cf0e9 3164 /* update finish MAC */
ashleymills 0:ff9ebe0cf0e9 3165 update_hs_hash(peer, data, data_length);
ashleymills 0:ff9ebe0cf0e9 3166
ashleymills 0:ff9ebe0cf0e9 3167 err = dtls_send_server_hello_msgs(ctx, peer);
ashleymills 0:ff9ebe0cf0e9 3168 if (err < 0) {
ashleymills 0:ff9ebe0cf0e9 3169 return err;
ashleymills 0:ff9ebe0cf0e9 3170 }
ashleymills 0:ff9ebe0cf0e9 3171 if (peer->handshake_params.cipher == TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 &&
ashleymills 0:ff9ebe0cf0e9 3172 ctx && ctx->h && ctx->h->verify_ecdsa_key)
ashleymills 0:ff9ebe0cf0e9 3173 peer->state = DTLS_STATE_WAIT_CLIENTCERTIFICATE;
ashleymills 0:ff9ebe0cf0e9 3174 else
ashleymills 0:ff9ebe0cf0e9 3175 peer->state = DTLS_STATE_WAIT_CLIENTKEYEXCHANGE;
ashleymills 0:ff9ebe0cf0e9 3176
ashleymills 0:ff9ebe0cf0e9 3177 /* after sending the ServerHelloDone, we expect the
ashleymills 0:ff9ebe0cf0e9 3178 * ClientKeyExchange (possibly containing the PSK id),
ashleymills 0:ff9ebe0cf0e9 3179 * followed by a ChangeCipherSpec and an encrypted Finished.
ashleymills 0:ff9ebe0cf0e9 3180 */
ashleymills 0:ff9ebe0cf0e9 3181
ashleymills 0:ff9ebe0cf0e9 3182 break;
ashleymills 0:ff9ebe0cf0e9 3183
ashleymills 0:ff9ebe0cf0e9 3184 case DTLS_HT_HELLO_REQUEST:
ashleymills 0:ff9ebe0cf0e9 3185
ashleymills 0:ff9ebe0cf0e9 3186 DBG("DTLS_HT_HELLO_REQUEST");
ashleymills 0:ff9ebe0cf0e9 3187 if (state != DTLS_STATE_CONNECTED) {
ashleymills 0:ff9ebe0cf0e9 3188 /* we should just ignore such packages when in handshake */
ashleymills 0:ff9ebe0cf0e9 3189 return 0;
ashleymills 0:ff9ebe0cf0e9 3190 }
ashleymills 0:ff9ebe0cf0e9 3191
ashleymills 0:ff9ebe0cf0e9 3192 /* send ClientHello with empty Cookie */
ashleymills 0:ff9ebe0cf0e9 3193 err = dtls_send_client_hello(ctx, peer, NULL, 0);
ashleymills 0:ff9ebe0cf0e9 3194 if (err < 0)
ashleymills 0:ff9ebe0cf0e9 3195 WARN("cannot send ClientHello");
ashleymills 0:ff9ebe0cf0e9 3196 else
ashleymills 0:ff9ebe0cf0e9 3197 peer->state = DTLS_STATE_CLIENTHELLO;
ashleymills 0:ff9ebe0cf0e9 3198
ashleymills 0:ff9ebe0cf0e9 3199 return err;
ashleymills 0:ff9ebe0cf0e9 3200 default:
ashleymills 0:ff9ebe0cf0e9 3201 DBG("unhandled message %d", data[0]);
ashleymills 0:ff9ebe0cf0e9 3202 return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE);
ashleymills 0:ff9ebe0cf0e9 3203 }
ashleymills 0:ff9ebe0cf0e9 3204
ashleymills 0:ff9ebe0cf0e9 3205 return err;
ashleymills 0:ff9ebe0cf0e9 3206 }
ashleymills 0:ff9ebe0cf0e9 3207
ashleymills 0:ff9ebe0cf0e9 3208 static int
ashleymills 0:ff9ebe0cf0e9 3209 handle_ccs(dtls_context_t *ctx, dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 3210 uint8 *record_header, uint8 *data, size_t data_length)
ashleymills 0:ff9ebe0cf0e9 3211 {
ashleymills 0:ff9ebe0cf0e9 3212 int err;
ashleymills 0:ff9ebe0cf0e9 3213 dtls_handshake_parameters_t *handshake = &peer->handshake_params;
ashleymills 0:ff9ebe0cf0e9 3214 dtls_security_parameters_t *security = &peer->security_params;
ashleymills 0:ff9ebe0cf0e9 3215
ashleymills 0:ff9ebe0cf0e9 3216 /* A CCS message is handled after a KeyExchange message was
ashleymills 0:ff9ebe0cf0e9 3217 * received from the client. When security parameters have been
ashleymills 0:ff9ebe0cf0e9 3218 * updated successfully and a ChangeCipherSpec message was sent
ashleymills 0:ff9ebe0cf0e9 3219 * by ourself, the security context is switched and the record
ashleymills 0:ff9ebe0cf0e9 3220 * sequence number is reset. */
ashleymills 0:ff9ebe0cf0e9 3221
ashleymills 0:ff9ebe0cf0e9 3222 if (!peer || peer->state != DTLS_STATE_WAIT_CLIENTCHANGECIPHERSPEC) {
ashleymills 0:ff9ebe0cf0e9 3223 WARN("expected ChangeCipherSpec during handshake");
ashleymills 0:ff9ebe0cf0e9 3224 return dtls_alert_fatal_create(DTLS_ALERT_UNEXPECTED_MESSAGE);
ashleymills 0:ff9ebe0cf0e9 3225 }
ashleymills 0:ff9ebe0cf0e9 3226
ashleymills 0:ff9ebe0cf0e9 3227 if (data_length < 1 || data[0] != 1)
ashleymills 0:ff9ebe0cf0e9 3228 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 3229
ashleymills 0:ff9ebe0cf0e9 3230 /* send change cipher spec message and switch to new configuration */
ashleymills 0:ff9ebe0cf0e9 3231 err = dtls_send_ccs(ctx, peer);
ashleymills 0:ff9ebe0cf0e9 3232 if (err < 0) {
ashleymills 0:ff9ebe0cf0e9 3233 WARN("cannot send CCS message");
ashleymills 0:ff9ebe0cf0e9 3234 return err;
ashleymills 0:ff9ebe0cf0e9 3235 }
ashleymills 0:ff9ebe0cf0e9 3236
ashleymills 0:ff9ebe0cf0e9 3237 err = calculate_key_block(ctx, handshake, security,
ashleymills 0:ff9ebe0cf0e9 3238 &peer->session);
ashleymills 0:ff9ebe0cf0e9 3239 if (err < 0) {
ashleymills 0:ff9ebe0cf0e9 3240 return err;
ashleymills 0:ff9ebe0cf0e9 3241 }
ashleymills 0:ff9ebe0cf0e9 3242
ashleymills 0:ff9ebe0cf0e9 3243 err = init_cipher(handshake, security, peer->role);
ashleymills 0:ff9ebe0cf0e9 3244 if (err < 0) {
ashleymills 0:ff9ebe0cf0e9 3245 return err;
ashleymills 0:ff9ebe0cf0e9 3246 }
ashleymills 0:ff9ebe0cf0e9 3247
ashleymills 0:ff9ebe0cf0e9 3248 inc_uint(uint16, peer->epoch);
ashleymills 0:ff9ebe0cf0e9 3249 memset(peer->rseq, 0, sizeof(peer->rseq));
ashleymills 0:ff9ebe0cf0e9 3250
ashleymills 0:ff9ebe0cf0e9 3251 peer->state = DTLS_STATE_WAIT_FINISHED;
ashleymills 0:ff9ebe0cf0e9 3252
ashleymills 0:ff9ebe0cf0e9 3253 dtls_debug_keyblock(security);
ashleymills 0:ff9ebe0cf0e9 3254
ashleymills 0:ff9ebe0cf0e9 3255 return 0;
ashleymills 0:ff9ebe0cf0e9 3256 }
ashleymills 0:ff9ebe0cf0e9 3257
ashleymills 0:ff9ebe0cf0e9 3258 /**
ashleymills 0:ff9ebe0cf0e9 3259 * Handles incoming Alert messages. This function returns \c 1 if the
ashleymills 0:ff9ebe0cf0e9 3260 * connection should be closed and the peer is to be invalidated.
ashleymills 0:ff9ebe0cf0e9 3261 */
ashleymills 0:ff9ebe0cf0e9 3262 static int
ashleymills 0:ff9ebe0cf0e9 3263 handle_alert(dtls_context_t *ctx, dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 3264 uint8 *record_header, uint8 *data, size_t data_length) {
ashleymills 0:ff9ebe0cf0e9 3265 int free_peer = 0; /* indicates whether to free peer */
ashleymills 0:ff9ebe0cf0e9 3266
ashleymills 0:ff9ebe0cf0e9 3267 if (data_length < 2)
ashleymills 0:ff9ebe0cf0e9 3268 return dtls_alert_fatal_create(DTLS_ALERT_DECODE_ERROR);
ashleymills 0:ff9ebe0cf0e9 3269
ashleymills 0:ff9ebe0cf0e9 3270 INFO("** Alert: level %d, description %d", data[0], data[1]);
ashleymills 0:ff9ebe0cf0e9 3271
ashleymills 0:ff9ebe0cf0e9 3272 if (!peer) {
ashleymills 0:ff9ebe0cf0e9 3273 WARN("got an alert for an unknown peer, we probably already removed it, ignore it");
ashleymills 0:ff9ebe0cf0e9 3274 return 0;
ashleymills 0:ff9ebe0cf0e9 3275 }
ashleymills 0:ff9ebe0cf0e9 3276
ashleymills 0:ff9ebe0cf0e9 3277 /* The peer object is invalidated for FATAL alerts and close
ashleymills 0:ff9ebe0cf0e9 3278 * notifies. This is done in two steps.: First, remove the object
ashleymills 0:ff9ebe0cf0e9 3279 * from our list of peers. After that, the event handler callback is
ashleymills 0:ff9ebe0cf0e9 3280 * invoked with the still existing peer object. Finally, the storage
ashleymills 0:ff9ebe0cf0e9 3281 * used by peer is released.
ashleymills 0:ff9ebe0cf0e9 3282 */
ashleymills 0:ff9ebe0cf0e9 3283 if (data[0] == DTLS_ALERT_LEVEL_FATAL || data[1] == DTLS_ALERT_CLOSE_NOTIFY) {
ashleymills 0:ff9ebe0cf0e9 3284 DBG("%d invalidate peer", data[1]);
ashleymills 0:ff9ebe0cf0e9 3285
ashleymills 0:ff9ebe0cf0e9 3286 #ifndef WITH_CONTIKI
ashleymills 0:ff9ebe0cf0e9 3287 HASH_DEL_PEER(ctx->peers, peer);
ashleymills 0:ff9ebe0cf0e9 3288 #else /* WITH_CONTIKI */
ashleymills 0:ff9ebe0cf0e9 3289 list_remove(ctx->peers, peer);
ashleymills 0:ff9ebe0cf0e9 3290
ashleymills 0:ff9ebe0cf0e9 3291 #ifndef NDEBUG
ashleymills 0:ff9ebe0cf0e9 3292 PRINTF("removed peer [");
ashleymills 0:ff9ebe0cf0e9 3293 PRINT6ADDR(&peer->session.addr);
ashleymills 0:ff9ebe0cf0e9 3294 PRINTF("]:%d", uip_ntohs(peer->session.port));
ashleymills 0:ff9ebe0cf0e9 3295 #endif
ashleymills 0:ff9ebe0cf0e9 3296 #endif /* WITH_CONTIKI */
ashleymills 0:ff9ebe0cf0e9 3297
ashleymills 0:ff9ebe0cf0e9 3298 free_peer = 1;
ashleymills 0:ff9ebe0cf0e9 3299
ashleymills 0:ff9ebe0cf0e9 3300 }
ashleymills 0:ff9ebe0cf0e9 3301
ashleymills 0:ff9ebe0cf0e9 3302 (void)CALL(ctx, event, &peer->session,
ashleymills 0:ff9ebe0cf0e9 3303 (dtls_alert_level_t)data[0], (unsigned short)data[1]);
ashleymills 0:ff9ebe0cf0e9 3304 switch (data[1]) {
ashleymills 0:ff9ebe0cf0e9 3305 case DTLS_ALERT_CLOSE_NOTIFY:
ashleymills 0:ff9ebe0cf0e9 3306 /* If state is DTLS_STATE_CLOSING, we have already sent a
ashleymills 0:ff9ebe0cf0e9 3307 * close_notify so, do not send that again. */
ashleymills 0:ff9ebe0cf0e9 3308 if (peer->state != DTLS_STATE_CLOSING) {
ashleymills 0:ff9ebe0cf0e9 3309 peer->state = DTLS_STATE_CLOSING;
ashleymills 0:ff9ebe0cf0e9 3310 dtls_alert(ctx, peer, DTLS_ALERT_LEVEL_FATAL, DTLS_ALERT_CLOSE_NOTIFY);
ashleymills 0:ff9ebe0cf0e9 3311 } else
ashleymills 0:ff9ebe0cf0e9 3312 peer->state = DTLS_STATE_CLOSED;
ashleymills 0:ff9ebe0cf0e9 3313 break;
ashleymills 0:ff9ebe0cf0e9 3314 default:
ashleymills 0:ff9ebe0cf0e9 3315 ;
ashleymills 0:ff9ebe0cf0e9 3316 }
ashleymills 0:ff9ebe0cf0e9 3317
ashleymills 0:ff9ebe0cf0e9 3318 if (free_peer) {
ashleymills 0:ff9ebe0cf0e9 3319 dtls_stop_retransmission(ctx, peer);
ashleymills 0:ff9ebe0cf0e9 3320 dtls_destory_peer(ctx, peer, 0);
ashleymills 0:ff9ebe0cf0e9 3321 }
ashleymills 0:ff9ebe0cf0e9 3322
ashleymills 0:ff9ebe0cf0e9 3323 return free_peer;
ashleymills 0:ff9ebe0cf0e9 3324 }
ashleymills 0:ff9ebe0cf0e9 3325
ashleymills 0:ff9ebe0cf0e9 3326 static int dtls_alert_send_from_err(dtls_context_t *ctx, dtls_peer_t *peer,
ashleymills 0:ff9ebe0cf0e9 3327 session_t *session, int err)
ashleymills 0:ff9ebe0cf0e9 3328 {
ashleymills 0:ff9ebe0cf0e9 3329 int level;
ashleymills 0:ff9ebe0cf0e9 3330 int desc;
ashleymills 0:ff9ebe0cf0e9 3331
ashleymills 0:ff9ebe0cf0e9 3332 if (err < -(1 << 8) && err > -(3 << 8)) {
ashleymills 0:ff9ebe0cf0e9 3333 level = ((-err) & 0xff00) >> 8;
ashleymills 0:ff9ebe0cf0e9 3334 desc = (-err) & 0xff;
ashleymills 0:ff9ebe0cf0e9 3335 if (!peer) {
ashleymills 0:ff9ebe0cf0e9 3336 peer = dtls_get_peer(ctx, session);
ashleymills 0:ff9ebe0cf0e9 3337 }
ashleymills 0:ff9ebe0cf0e9 3338 if (peer) {
ashleymills 0:ff9ebe0cf0e9 3339 return dtls_alert(ctx, peer, level, desc);
ashleymills 0:ff9ebe0cf0e9 3340 }
ashleymills 0:ff9ebe0cf0e9 3341 } else if (err == -1) {
ashleymills 0:ff9ebe0cf0e9 3342 if (!peer) {
ashleymills 0:ff9ebe0cf0e9 3343 peer = dtls_get_peer(ctx, session);
ashleymills 0:ff9ebe0cf0e9 3344 }
ashleymills 0:ff9ebe0cf0e9 3345 if (peer) {
ashleymills 0:ff9ebe0cf0e9 3346 return dtls_alert(ctx, peer, DTLS_ALERT_LEVEL_FATAL, DTLS_ALERT_INTERNAL_ERROR);
ashleymills 0:ff9ebe0cf0e9 3347 }
ashleymills 0:ff9ebe0cf0e9 3348 }
ashleymills 0:ff9ebe0cf0e9 3349 return -1;
ashleymills 0:ff9ebe0cf0e9 3350 }
ashleymills 0:ff9ebe0cf0e9 3351
ashleymills 0:ff9ebe0cf0e9 3352 /**
ashleymills 0:ff9ebe0cf0e9 3353 * Handles incoming data as DTLS message from given peer.
ashleymills 0:ff9ebe0cf0e9 3354 */
ashleymills 0:ff9ebe0cf0e9 3355 int
ashleymills 0:ff9ebe0cf0e9 3356 dtls_handle_message(dtls_context_t *ctx,
ashleymills 0:ff9ebe0cf0e9 3357 session_t *session,
ashleymills 0:ff9ebe0cf0e9 3358 uint8 *msg, int msglen) {
ashleymills 0:ff9ebe0cf0e9 3359 dtls_peer_t *peer = NULL;
ashleymills 0:ff9ebe0cf0e9 3360 unsigned int rlen; /* record length */
ashleymills 0:ff9ebe0cf0e9 3361 uint8 *data; /* (decrypted) payload */
ashleymills 0:ff9ebe0cf0e9 3362 size_t data_length; /* length of decrypted payload
ashleymills 0:ff9ebe0cf0e9 3363 (without MAC and padding) */
ashleymills 0:ff9ebe0cf0e9 3364 int err;
ashleymills 0:ff9ebe0cf0e9 3365
ashleymills 0:ff9ebe0cf0e9 3366 /* check if we have DTLS state for addr/port/ifindex */
ashleymills 0:ff9ebe0cf0e9 3367 peer = dtls_get_peer(ctx, session);
ashleymills 0:ff9ebe0cf0e9 3368
ashleymills 0:ff9ebe0cf0e9 3369 if (!peer) {
ashleymills 0:ff9ebe0cf0e9 3370 DBG("dtls_handle_message: PEER NOT FOUND");
ashleymills 0:ff9ebe0cf0e9 3371 dtls_dsrv_log_addr(LOG_DEBUG, "peer addr", session);
ashleymills 0:ff9ebe0cf0e9 3372 } else {
ashleymills 0:ff9ebe0cf0e9 3373 DBG("dtls_handle_message: FOUND PEER");
ashleymills 0:ff9ebe0cf0e9 3374 }
ashleymills 0:ff9ebe0cf0e9 3375
ashleymills 0:ff9ebe0cf0e9 3376 /* FIXME: check sequence number of record and drop message if the
ashleymills 0:ff9ebe0cf0e9 3377 * number is not exactly the last number that we have responded to + 1.
ashleymills 0:ff9ebe0cf0e9 3378 * Otherwise, stop retransmissions for this specific peer and
ashleymills 0:ff9ebe0cf0e9 3379 * continue processing. */
ashleymills 0:ff9ebe0cf0e9 3380 if (peer) {
ashleymills 0:ff9ebe0cf0e9 3381 dtls_stop_retransmission(ctx, peer);
ashleymills 0:ff9ebe0cf0e9 3382 }
ashleymills 0:ff9ebe0cf0e9 3383
ashleymills 0:ff9ebe0cf0e9 3384 while ((rlen = is_record(msg,msglen))) {
ashleymills 0:ff9ebe0cf0e9 3385 dtls_peer_type role;
ashleymills 0:ff9ebe0cf0e9 3386 dtls_state_t state;
ashleymills 0:ff9ebe0cf0e9 3387
ashleymills 0:ff9ebe0cf0e9 3388 DBG("got packet %d (%d bytes)", msg[0], rlen);
ashleymills 0:ff9ebe0cf0e9 3389 if (peer) {
ashleymills 0:ff9ebe0cf0e9 3390 /* skip packet if it is from a different epoch */
ashleymills 0:ff9ebe0cf0e9 3391 if (memcmp(DTLS_RECORD_HEADER(msg)->epoch,
ashleymills 0:ff9ebe0cf0e9 3392 peer->epoch, sizeof(uint16)) != 0)
ashleymills 0:ff9ebe0cf0e9 3393 goto next;
ashleymills 0:ff9ebe0cf0e9 3394
ashleymills 0:ff9ebe0cf0e9 3395 if (!decrypt_verify(peer, msg, rlen, &data, &data_length)) {
ashleymills 0:ff9ebe0cf0e9 3396 INFO("decrypt_verify() failed");
ashleymills 0:ff9ebe0cf0e9 3397 goto next;
ashleymills 0:ff9ebe0cf0e9 3398 }
ashleymills 0:ff9ebe0cf0e9 3399 role = peer->role;
ashleymills 0:ff9ebe0cf0e9 3400 state = peer->state;
ashleymills 0:ff9ebe0cf0e9 3401 } else {
ashleymills 0:ff9ebe0cf0e9 3402 /* is_record() ensures that msg contains at least a record header */
ashleymills 0:ff9ebe0cf0e9 3403 data = msg + DTLS_RH_LENGTH;
ashleymills 0:ff9ebe0cf0e9 3404 data_length = rlen - DTLS_RH_LENGTH;
ashleymills 0:ff9ebe0cf0e9 3405 state = DTLS_STATE_WAIT_CLIENTHELLO;
ashleymills 0:ff9ebe0cf0e9 3406 role = DTLS_SERVER;
ashleymills 0:ff9ebe0cf0e9 3407 }
ashleymills 0:ff9ebe0cf0e9 3408
ashleymills 0:ff9ebe0cf0e9 3409 dtls_dsrv_hexdump_log(LOG_DEBUG, "receive header", msg,
ashleymills 0:ff9ebe0cf0e9 3410 sizeof(dtls_record_header_t), 1);
ashleymills 0:ff9ebe0cf0e9 3411 dtls_dsrv_hexdump_log(LOG_DEBUG, "receive unencrypted", data, data_length, 1);
ashleymills 0:ff9ebe0cf0e9 3412
ashleymills 0:ff9ebe0cf0e9 3413 /* Handle received record according to the first byte of the
ashleymills 0:ff9ebe0cf0e9 3414 * message, i.e. the subprotocol. We currently do not support
ashleymills 0:ff9ebe0cf0e9 3415 * combining multiple fragments of one type into a single
ashleymills 0:ff9ebe0cf0e9 3416 * record. */
ashleymills 0:ff9ebe0cf0e9 3417
ashleymills 0:ff9ebe0cf0e9 3418 switch (msg[0]) {
ashleymills 0:ff9ebe0cf0e9 3419
ashleymills 0:ff9ebe0cf0e9 3420 case DTLS_CT_CHANGE_CIPHER_SPEC:
ashleymills 0:ff9ebe0cf0e9 3421 err = handle_ccs(ctx, peer, msg, data, data_length);
ashleymills 0:ff9ebe0cf0e9 3422 if (err < 0) {
ashleymills 0:ff9ebe0cf0e9 3423 WARN("error while handling ChangeCipherSpec package");
ashleymills 0:ff9ebe0cf0e9 3424 dtls_alert_send_from_err(ctx, peer, session, err);
ashleymills 0:ff9ebe0cf0e9 3425 return err;
ashleymills 0:ff9ebe0cf0e9 3426 }
ashleymills 0:ff9ebe0cf0e9 3427 break;
ashleymills 0:ff9ebe0cf0e9 3428
ashleymills 0:ff9ebe0cf0e9 3429 case DTLS_CT_ALERT:
ashleymills 0:ff9ebe0cf0e9 3430 err = handle_alert(ctx, peer, msg, data, data_length);
ashleymills 0:ff9ebe0cf0e9 3431 if (err < 0) {
ashleymills 0:ff9ebe0cf0e9 3432 WARN("received wrong package");
ashleymills 0:ff9ebe0cf0e9 3433 /* handle alert has invalidated peer */
ashleymills 0:ff9ebe0cf0e9 3434 peer = NULL;
ashleymills 0:ff9ebe0cf0e9 3435 return err;
ashleymills 0:ff9ebe0cf0e9 3436 }
ashleymills 0:ff9ebe0cf0e9 3437 break;
ashleymills 0:ff9ebe0cf0e9 3438
ashleymills 0:ff9ebe0cf0e9 3439 case DTLS_CT_HANDSHAKE:
ashleymills 0:ff9ebe0cf0e9 3440 err = handle_handshake(ctx, peer, session, role, state, msg, data, data_length);
ashleymills 0:ff9ebe0cf0e9 3441 DBG("Returned from handle_handshake: %d",err);
ashleymills 0:ff9ebe0cf0e9 3442 if (err < 0) {
ashleymills 0:ff9ebe0cf0e9 3443 WARN("error while handling handshake package");
ashleymills 0:ff9ebe0cf0e9 3444 dtls_alert_send_from_err(ctx, peer, session, err);
ashleymills 0:ff9ebe0cf0e9 3445 return err;
ashleymills 0:ff9ebe0cf0e9 3446 }
ashleymills 0:ff9ebe0cf0e9 3447 if (peer && peer->state == DTLS_STATE_CONNECTED) {
ashleymills 0:ff9ebe0cf0e9 3448 DBG("DTLS_STATE_CONNECTED");
ashleymills 0:ff9ebe0cf0e9 3449 /* stop retransmissions */
ashleymills 0:ff9ebe0cf0e9 3450 dtls_stop_retransmission(ctx, peer);
ashleymills 0:ff9ebe0cf0e9 3451 CALL(ctx, event, &peer->session, 0, DTLS_EVENT_CONNECTED);
ashleymills 0:ff9ebe0cf0e9 3452 }
ashleymills 0:ff9ebe0cf0e9 3453 break;
ashleymills 0:ff9ebe0cf0e9 3454
ashleymills 0:ff9ebe0cf0e9 3455 case DTLS_CT_APPLICATION_DATA:
ashleymills 0:ff9ebe0cf0e9 3456 INFO("** application data:");
ashleymills 0:ff9ebe0cf0e9 3457 if (!peer) {
ashleymills 0:ff9ebe0cf0e9 3458 WARN("no peer available, send an alert");
ashleymills 0:ff9ebe0cf0e9 3459 dtls_alert(ctx, peer, DTLS_ALERT_LEVEL_FATAL, DTLS_ALERT_UNEXPECTED_MESSAGE);
ashleymills 0:ff9ebe0cf0e9 3460 return -1;
ashleymills 0:ff9ebe0cf0e9 3461 }
ashleymills 0:ff9ebe0cf0e9 3462 CALL(ctx, read, &peer->session, data, data_length);
ashleymills 0:ff9ebe0cf0e9 3463 break;
ashleymills 0:ff9ebe0cf0e9 3464 default:
ashleymills 0:ff9ebe0cf0e9 3465 INFO("dropped unknown message of type %d",msg[0]);
ashleymills 0:ff9ebe0cf0e9 3466 }
ashleymills 0:ff9ebe0cf0e9 3467
ashleymills 0:ff9ebe0cf0e9 3468 next:
ashleymills 0:ff9ebe0cf0e9 3469 /* advance msg by length of ciphertext */
ashleymills 0:ff9ebe0cf0e9 3470 msg += rlen;
ashleymills 0:ff9ebe0cf0e9 3471 msglen -= rlen;
ashleymills 0:ff9ebe0cf0e9 3472 }
ashleymills 0:ff9ebe0cf0e9 3473 DBG("Leaving dtls_handle_message");
ashleymills 0:ff9ebe0cf0e9 3474 return 0;
ashleymills 0:ff9ebe0cf0e9 3475 }
ashleymills 0:ff9ebe0cf0e9 3476
ashleymills 0:ff9ebe0cf0e9 3477 dtls_context_t *
ashleymills 0:ff9ebe0cf0e9 3478 dtls_new_context(void *app_data) {
ashleymills 0:ff9ebe0cf0e9 3479 dtls_context_t *c;
ashleymills 0:ff9ebe0cf0e9 3480 dtls_tick_t now;
ashleymills 0:ff9ebe0cf0e9 3481 #ifndef WITH_CONTIKI
ashleymills 0:ff9ebe0cf0e9 3482 FILE *urandom = fopen("/dev/urandom", "r");
ashleymills 0:ff9ebe0cf0e9 3483 unsigned char buf[sizeof(unsigned long)];
ashleymills 0:ff9ebe0cf0e9 3484 #endif /* WITH_CONTIKI */
ashleymills 0:ff9ebe0cf0e9 3485
ashleymills 0:ff9ebe0cf0e9 3486 dtls_ticks(&now);
ashleymills 0:ff9ebe0cf0e9 3487 #ifdef WITH_CONTIKI
ashleymills 0:ff9ebe0cf0e9 3488 /* FIXME: need something better to init PRNG here */
ashleymills 0:ff9ebe0cf0e9 3489 prng_init(now);
ashleymills 0:ff9ebe0cf0e9 3490 #else /* WITH_CONTIKI */
ashleymills 0:ff9ebe0cf0e9 3491 /*
ashleymills 0:ff9ebe0cf0e9 3492 if (!urandom) {
ashleymills 0:ff9ebe0cf0e9 3493 DBG("cannot initialize PRNG");
ashleymills 0:ff9ebe0cf0e9 3494 return NULL;
ashleymills 0:ff9ebe0cf0e9 3495 }
ashleymills 0:ff9ebe0cf0e9 3496
ashleymills 0:ff9ebe0cf0e9 3497 if (fread(buf, 1, sizeof(buf), urandom) != sizeof(buf)) {
ashleymills 0:ff9ebe0cf0e9 3498 dsrv_log(LOG_EMERG, "cannot initialize PRNG");
ashleymills 0:ff9ebe0cf0e9 3499 return NULL;
ashleymills 0:ff9ebe0cf0e9 3500 }
ashleymills 0:ff9ebe0cf0e9 3501
ashleymills 0:ff9ebe0cf0e9 3502 fclose(urandom);
ashleymills 0:ff9ebe0cf0e9 3503 prng_init((unsigned long)*buf);
ashleymills 0:ff9ebe0cf0e9 3504 */
ashleymills 0:ff9ebe0cf0e9 3505 // just randomly flip some bits
ashleymills 0:ff9ebe0cf0e9 3506 unsigned long mask = 0x0000;
ashleymills 0:ff9ebe0cf0e9 3507 for(int i=0; i<sizeof(buf); i++) {
ashleymills 0:ff9ebe0cf0e9 3508 // XXX need to flip some bits
ashleymills 0:ff9ebe0cf0e9 3509 }
ashleymills 0:ff9ebe0cf0e9 3510 prng_init((unsigned long)*buf);
ashleymills 0:ff9ebe0cf0e9 3511 #endif /* WITH_CONTIKI */
ashleymills 0:ff9ebe0cf0e9 3512
ashleymills 0:ff9ebe0cf0e9 3513 c = &the_dtls_context;
ashleymills 0:ff9ebe0cf0e9 3514
ashleymills 0:ff9ebe0cf0e9 3515 memset(c, 0, sizeof(dtls_context_t));
ashleymills 0:ff9ebe0cf0e9 3516 c->app = app_data;
ashleymills 0:ff9ebe0cf0e9 3517
ashleymills 0:ff9ebe0cf0e9 3518 LIST_STRUCT_INIT(c, sendqueue);
ashleymills 0:ff9ebe0cf0e9 3519
ashleymills 0:ff9ebe0cf0e9 3520 #ifdef WITH_CONTIKI
ashleymills 0:ff9ebe0cf0e9 3521 LIST_STRUCT_INIT(c, peers);
ashleymills 0:ff9ebe0cf0e9 3522 /* LIST_STRUCT_INIT(c, key_store); */
ashleymills 0:ff9ebe0cf0e9 3523
ashleymills 0:ff9ebe0cf0e9 3524 process_start(&dtls_retransmit_process, (char *)c);
ashleymills 0:ff9ebe0cf0e9 3525 PROCESS_CONTEXT_BEGIN(&dtls_retransmit_process);
ashleymills 0:ff9ebe0cf0e9 3526 /* the retransmit timer must be initialized to some large value */
ashleymills 0:ff9ebe0cf0e9 3527 etimer_set(&c->retransmit_timer, 0xFFFF);
ashleymills 0:ff9ebe0cf0e9 3528 PROCESS_CONTEXT_END(&coap_retransmit_process);
ashleymills 0:ff9ebe0cf0e9 3529 #endif /* WITH_CONTIKI */
ashleymills 0:ff9ebe0cf0e9 3530
ashleymills 0:ff9ebe0cf0e9 3531 if (prng(c->cookie_secret, DTLS_COOKIE_SECRET_LENGTH))
ashleymills 0:ff9ebe0cf0e9 3532 c->cookie_secret_age = now;
ashleymills 0:ff9ebe0cf0e9 3533 else
ashleymills 0:ff9ebe0cf0e9 3534 goto error;
ashleymills 0:ff9ebe0cf0e9 3535
ashleymills 0:ff9ebe0cf0e9 3536 return c;
ashleymills 0:ff9ebe0cf0e9 3537
ashleymills 0:ff9ebe0cf0e9 3538 error:
ashleymills 0:ff9ebe0cf0e9 3539 DBG("cannot create DTLS context");
ashleymills 0:ff9ebe0cf0e9 3540 if (c)
ashleymills 0:ff9ebe0cf0e9 3541 dtls_free_context(c);
ashleymills 0:ff9ebe0cf0e9 3542 return NULL;
ashleymills 0:ff9ebe0cf0e9 3543 }
ashleymills 0:ff9ebe0cf0e9 3544
ashleymills 0:ff9ebe0cf0e9 3545 void dtls_free_context(dtls_context_t *ctx) {
ashleymills 0:ff9ebe0cf0e9 3546 dtls_peer_t *p;
ashleymills 0:ff9ebe0cf0e9 3547
ashleymills 0:ff9ebe0cf0e9 3548 #ifndef WITH_CONTIKI
ashleymills 0:ff9ebe0cf0e9 3549 dtls_peer_t *tmp;
ashleymills 0:ff9ebe0cf0e9 3550
ashleymills 0:ff9ebe0cf0e9 3551 if (ctx->peers) {
ashleymills 0:ff9ebe0cf0e9 3552 HASH_ITER(hh, ctx->peers, p, tmp) {
ashleymills 0:ff9ebe0cf0e9 3553 dtls_destory_peer(ctx, p, 1);
ashleymills 0:ff9ebe0cf0e9 3554 }
ashleymills 0:ff9ebe0cf0e9 3555 }
ashleymills 0:ff9ebe0cf0e9 3556 #else /* WITH_CONTIKI */
ashleymills 0:ff9ebe0cf0e9 3557 for (p = list_head(ctx->peers); p; p = list_item_next(p))
ashleymills 0:ff9ebe0cf0e9 3558 dtls_destory_peer(ctx, p, 1);
ashleymills 0:ff9ebe0cf0e9 3559 #endif /* WITH_CONTIKI */
ashleymills 0:ff9ebe0cf0e9 3560 }
ashleymills 0:ff9ebe0cf0e9 3561
ashleymills 0:ff9ebe0cf0e9 3562 int
ashleymills 0:ff9ebe0cf0e9 3563 dtls_connect_peer(dtls_context_t *ctx, dtls_peer_t *peer) {
ashleymills 0:ff9ebe0cf0e9 3564 int res;
ashleymills 0:ff9ebe0cf0e9 3565
ashleymills 0:ff9ebe0cf0e9 3566 assert(peer);
ashleymills 0:ff9ebe0cf0e9 3567 if (!peer)
ashleymills 0:ff9ebe0cf0e9 3568 return -1;
ashleymills 0:ff9ebe0cf0e9 3569
ashleymills 0:ff9ebe0cf0e9 3570 /* check if the same peer is already in our list */
ashleymills 0:ff9ebe0cf0e9 3571 if (peer == dtls_get_peer(ctx, &peer->session)) {
ashleymills 0:ff9ebe0cf0e9 3572 DBG("found peer, try to re-connect");
ashleymills 0:ff9ebe0cf0e9 3573 /* FIXME: send HelloRequest if we are server,
ashleymills 0:ff9ebe0cf0e9 3574 ClientHello with good cookie if client */
ashleymills 0:ff9ebe0cf0e9 3575 return 0;
ashleymills 0:ff9ebe0cf0e9 3576 }
ashleymills 0:ff9ebe0cf0e9 3577
ashleymills 0:ff9ebe0cf0e9 3578 /* set peer role to server: */
ashleymills 0:ff9ebe0cf0e9 3579 peer->role = DTLS_CLIENT;
ashleymills 0:ff9ebe0cf0e9 3580
ashleymills 0:ff9ebe0cf0e9 3581 dtls_add_peer(ctx, peer);
ashleymills 0:ff9ebe0cf0e9 3582
ashleymills 0:ff9ebe0cf0e9 3583 /* send ClientHello with empty Cookie */
ashleymills 0:ff9ebe0cf0e9 3584 res = dtls_send_client_hello(ctx, peer, NULL, 0);
ashleymills 0:ff9ebe0cf0e9 3585 if (res < 0)
ashleymills 0:ff9ebe0cf0e9 3586 WARN("cannot send ClientHello");
ashleymills 0:ff9ebe0cf0e9 3587 else
ashleymills 0:ff9ebe0cf0e9 3588 peer->state = DTLS_STATE_CLIENTHELLO;
ashleymills 0:ff9ebe0cf0e9 3589
ashleymills 0:ff9ebe0cf0e9 3590 return res;
ashleymills 0:ff9ebe0cf0e9 3591 }
ashleymills 0:ff9ebe0cf0e9 3592
ashleymills 0:ff9ebe0cf0e9 3593 int
ashleymills 0:ff9ebe0cf0e9 3594 dtls_connect(dtls_context_t *ctx, const session_t *dst) {
ashleymills 0:ff9ebe0cf0e9 3595 dtls_peer_t *peer;
ashleymills 0:ff9ebe0cf0e9 3596
ashleymills 0:ff9ebe0cf0e9 3597 peer = dtls_get_peer(ctx, dst);
ashleymills 0:ff9ebe0cf0e9 3598
ashleymills 0:ff9ebe0cf0e9 3599 if (!peer)
ashleymills 0:ff9ebe0cf0e9 3600 peer = dtls_new_peer(dst);
ashleymills 0:ff9ebe0cf0e9 3601
ashleymills 0:ff9ebe0cf0e9 3602 if (!peer) {
ashleymills 0:ff9ebe0cf0e9 3603 DBG("cannot create new peer");
ashleymills 0:ff9ebe0cf0e9 3604 return -1;
ashleymills 0:ff9ebe0cf0e9 3605 }
ashleymills 0:ff9ebe0cf0e9 3606
ashleymills 0:ff9ebe0cf0e9 3607 return dtls_connect_peer(ctx, peer);
ashleymills 0:ff9ebe0cf0e9 3608 }
ashleymills 0:ff9ebe0cf0e9 3609
ashleymills 0:ff9ebe0cf0e9 3610 static void
ashleymills 0:ff9ebe0cf0e9 3611 dtls_retransmit(dtls_context_t *context, netq_t *node) {
ashleymills 0:ff9ebe0cf0e9 3612 if (!context || !node)
ashleymills 0:ff9ebe0cf0e9 3613 return;
ashleymills 0:ff9ebe0cf0e9 3614
ashleymills 0:ff9ebe0cf0e9 3615 /* re-initialize timeout when maximum number of retransmissions are not reached yet */
ashleymills 0:ff9ebe0cf0e9 3616 if (node->retransmit_cnt < DTLS_DEFAULT_MAX_RETRANSMIT) {
ashleymills 0:ff9ebe0cf0e9 3617 unsigned char sendbuf[DTLS_MAX_BUF];
ashleymills 0:ff9ebe0cf0e9 3618 size_t len = sizeof(sendbuf);
ashleymills 0:ff9ebe0cf0e9 3619
ashleymills 0:ff9ebe0cf0e9 3620 node->retransmit_cnt++;
ashleymills 0:ff9ebe0cf0e9 3621 node->t += (node->timeout << node->retransmit_cnt);
ashleymills 0:ff9ebe0cf0e9 3622 netq_insert_node((netq_t **)context->sendqueue, node);
ashleymills 0:ff9ebe0cf0e9 3623
ashleymills 0:ff9ebe0cf0e9 3624 DBG("** retransmit packet");
ashleymills 0:ff9ebe0cf0e9 3625
ashleymills 0:ff9ebe0cf0e9 3626 if (dtls_prepare_record(node->peer, DTLS_CT_HANDSHAKE,
ashleymills 0:ff9ebe0cf0e9 3627 (uint8 **)&(node->data), &(node->length), 1,
ashleymills 0:ff9ebe0cf0e9 3628 sendbuf, &len) > 0) {
ashleymills 0:ff9ebe0cf0e9 3629
ashleymills 0:ff9ebe0cf0e9 3630 dtls_dsrv_hexdump_log(LOG_DEBUG, "retransmit header", sendbuf,
ashleymills 0:ff9ebe0cf0e9 3631 sizeof(dtls_record_header_t), 1);
ashleymills 0:ff9ebe0cf0e9 3632 dtls_dsrv_hexdump_log(LOG_DEBUG, "retransmit unencrypted", node->data,
ashleymills 0:ff9ebe0cf0e9 3633 node->length, 1);
ashleymills 0:ff9ebe0cf0e9 3634
ashleymills 0:ff9ebe0cf0e9 3635 (void)CALL(context, write, &node->peer->session, sendbuf, len);
ashleymills 0:ff9ebe0cf0e9 3636 }
ashleymills 0:ff9ebe0cf0e9 3637 return;
ashleymills 0:ff9ebe0cf0e9 3638 }
ashleymills 0:ff9ebe0cf0e9 3639
ashleymills 0:ff9ebe0cf0e9 3640 /* no more retransmissions, remove node from system */
ashleymills 0:ff9ebe0cf0e9 3641
ashleymills 0:ff9ebe0cf0e9 3642 DBG("** removed transaction");
ashleymills 0:ff9ebe0cf0e9 3643
ashleymills 0:ff9ebe0cf0e9 3644 /* And finally delete the node */
ashleymills 0:ff9ebe0cf0e9 3645 netq_node_free(node);
ashleymills 0:ff9ebe0cf0e9 3646 }
ashleymills 0:ff9ebe0cf0e9 3647
ashleymills 0:ff9ebe0cf0e9 3648 static void
ashleymills 0:ff9ebe0cf0e9 3649 dtls_stop_retransmission(dtls_context_t *context, dtls_peer_t *peer) {
ashleymills 0:ff9ebe0cf0e9 3650 void *node;
ashleymills 0:ff9ebe0cf0e9 3651 node = list_head((list_t)context->sendqueue);
ashleymills 0:ff9ebe0cf0e9 3652
ashleymills 0:ff9ebe0cf0e9 3653 while (node) {
ashleymills 0:ff9ebe0cf0e9 3654 if (dtls_session_equals(&((netq_t *)node)->peer->session,
ashleymills 0:ff9ebe0cf0e9 3655 &peer->session)) {
ashleymills 0:ff9ebe0cf0e9 3656 void *tmp = node;
ashleymills 0:ff9ebe0cf0e9 3657 node = list_item_next(node);
ashleymills 0:ff9ebe0cf0e9 3658 list_remove((list_t)context->sendqueue, tmp);
ashleymills 0:ff9ebe0cf0e9 3659 netq_node_free((netq_t *)tmp);
ashleymills 0:ff9ebe0cf0e9 3660 } else
ashleymills 0:ff9ebe0cf0e9 3661 node = list_item_next(node);
ashleymills 0:ff9ebe0cf0e9 3662 }
ashleymills 0:ff9ebe0cf0e9 3663 }
ashleymills 0:ff9ebe0cf0e9 3664
ashleymills 0:ff9ebe0cf0e9 3665 void
ashleymills 0:ff9ebe0cf0e9 3666 dtls_check_retransmit(dtls_context_t *context, clock_time_t *next) {
ashleymills 0:ff9ebe0cf0e9 3667 dtls_tick_t now;
ashleymills 0:ff9ebe0cf0e9 3668 netq_t *node = netq_head((netq_t **)context->sendqueue);
ashleymills 0:ff9ebe0cf0e9 3669
ashleymills 0:ff9ebe0cf0e9 3670 dtls_ticks(&now);
ashleymills 0:ff9ebe0cf0e9 3671 while (node && node->t <= now) {
ashleymills 0:ff9ebe0cf0e9 3672 netq_pop_first((netq_t **)context->sendqueue);
ashleymills 0:ff9ebe0cf0e9 3673 dtls_retransmit(context, node);
ashleymills 0:ff9ebe0cf0e9 3674 node = netq_head((netq_t **)context->sendqueue);
ashleymills 0:ff9ebe0cf0e9 3675 }
ashleymills 0:ff9ebe0cf0e9 3676
ashleymills 0:ff9ebe0cf0e9 3677 if (next && node)
ashleymills 0:ff9ebe0cf0e9 3678 *next = node->t;
ashleymills 0:ff9ebe0cf0e9 3679 }
ashleymills 0:ff9ebe0cf0e9 3680
ashleymills 0:ff9ebe0cf0e9 3681 #ifdef WITH_CONTIKI
ashleymills 0:ff9ebe0cf0e9 3682 /*---------------------------------------------------------------------------*/
ashleymills 0:ff9ebe0cf0e9 3683 /* message retransmission */
ashleymills 0:ff9ebe0cf0e9 3684 /*---------------------------------------------------------------------------*/
ashleymills 0:ff9ebe0cf0e9 3685 PROCESS_THREAD(dtls_retransmit_process, ev, data)
ashleymills 0:ff9ebe0cf0e9 3686 {
ashleymills 0:ff9ebe0cf0e9 3687 clock_time_t now;
ashleymills 0:ff9ebe0cf0e9 3688 netq_t *node;
ashleymills 0:ff9ebe0cf0e9 3689
ashleymills 0:ff9ebe0cf0e9 3690 PROCESS_BEGIN();
ashleymills 0:ff9ebe0cf0e9 3691
ashleymills 0:ff9ebe0cf0e9 3692 DBG("Started DTLS retransmit process\r");
ashleymills 0:ff9ebe0cf0e9 3693
ashleymills 0:ff9ebe0cf0e9 3694 while(1) {
ashleymills 0:ff9ebe0cf0e9 3695 PROCESS_YIELD();
ashleymills 0:ff9ebe0cf0e9 3696 if (ev == PROCESS_EVENT_TIMER) {
ashleymills 0:ff9ebe0cf0e9 3697 if (etimer_expired(&the_dtls_context.retransmit_timer)) {
ashleymills 0:ff9ebe0cf0e9 3698
ashleymills 0:ff9ebe0cf0e9 3699 node = list_head(the_dtls_context.sendqueue);
ashleymills 0:ff9ebe0cf0e9 3700
ashleymills 0:ff9ebe0cf0e9 3701 now = clock_time();
ashleymills 0:ff9ebe0cf0e9 3702 while (node && node->t <= now) {
ashleymills 0:ff9ebe0cf0e9 3703 dtls_retransmit(&the_dtls_context, list_pop(the_dtls_context.sendqueue));
ashleymills 0:ff9ebe0cf0e9 3704 node = list_head(the_dtls_context.sendqueue);
ashleymills 0:ff9ebe0cf0e9 3705 }
ashleymills 0:ff9ebe0cf0e9 3706
ashleymills 0:ff9ebe0cf0e9 3707 /* need to set timer to some value even if no nextpdu is available */
ashleymills 0:ff9ebe0cf0e9 3708 etimer_set(&the_dtls_context.retransmit_timer,
ashleymills 0:ff9ebe0cf0e9 3709 node ? node->t - now : 0xFFFF);
ashleymills 0:ff9ebe0cf0e9 3710 }
ashleymills 0:ff9ebe0cf0e9 3711 }
ashleymills 0:ff9ebe0cf0e9 3712 }
ashleymills 0:ff9ebe0cf0e9 3713
ashleymills 0:ff9ebe0cf0e9 3714 PROCESS_END();
ashleymills 0:ff9ebe0cf0e9 3715 }
ashleymills 0:ff9ebe0cf0e9 3716 #endif /* WITH_CONTIKI */