mbed port of tinydtls

Committer:
ashleymills
Date:
Fri Oct 11 08:46:21 2013 +0000
Revision:
1:bc8a649bad13
Parent:
0:04990d454f45
Cleaned up all the debug stuff I added finding the hash table bug.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ashleymills 0:04990d454f45 1 /* dtls -- a very basic DTLS implementation
ashleymills 0:04990d454f45 2 *
ashleymills 0:04990d454f45 3 * Copyright (C) 2011--2012 Olaf Bergmann <bergmann@tzi.org>
ashleymills 0:04990d454f45 4 *
ashleymills 0:04990d454f45 5 * Permission is hereby granted, free of charge, to any person
ashleymills 0:04990d454f45 6 * obtaining a copy of this software and associated documentation
ashleymills 0:04990d454f45 7 * files (the "Software"), to deal in the Software without
ashleymills 0:04990d454f45 8 * restriction, including without limitation the rights to use, copy,
ashleymills 0:04990d454f45 9 * modify, merge, publish, distribute, sublicense, and/or sell copies
ashleymills 0:04990d454f45 10 * of the Software, and to permit persons to whom the Software is
ashleymills 0:04990d454f45 11 * furnished to do so, subject to the following conditions:
ashleymills 0:04990d454f45 12 *
ashleymills 0:04990d454f45 13 * The above copyright notice and this permission notice shall be
ashleymills 0:04990d454f45 14 * included in all copies or substantial portions of the Software.
ashleymills 0:04990d454f45 15 *
ashleymills 0:04990d454f45 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
ashleymills 0:04990d454f45 17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
ashleymills 0:04990d454f45 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
ashleymills 0:04990d454f45 19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
ashleymills 0:04990d454f45 20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ashleymills 0:04990d454f45 21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
ashleymills 0:04990d454f45 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
ashleymills 0:04990d454f45 23 * SOFTWARE.
ashleymills 0:04990d454f45 24 */
ashleymills 0:04990d454f45 25
ashleymills 0:04990d454f45 26 #include <stdio.h>
ashleymills 0:04990d454f45 27 #ifdef HAVE_ASSERT_H
ashleymills 0:04990d454f45 28 #include <assert.h>
ashleymills 0:04990d454f45 29 #endif
ashleymills 0:04990d454f45 30
ashleymills 0:04990d454f45 31 #include "global.h"
ashleymills 0:04990d454f45 32 #include "debug.h"
ashleymills 0:04990d454f45 33 #include "numeric.h"
ashleymills 0:04990d454f45 34 #include "dtls.h"
ashleymills 0:04990d454f45 35 #include "crypto.h"
ashleymills 0:04990d454f45 36 #include "ccm.h"
ashleymills 0:04990d454f45 37
ashleymills 0:04990d454f45 38 #ifndef WITH_CONTIKI
ashleymills 0:04990d454f45 39 #include <stdlib.h>
ashleymills 0:04990d454f45 40
ashleymills 0:04990d454f45 41 static inline dtls_cipher_context_t *
ashleymills 0:04990d454f45 42 dtls_cipher_context_new() {
ashleymills 0:04990d454f45 43 return (dtls_cipher_context_t *)malloc(sizeof(dtls_cipher_context_t));
ashleymills 0:04990d454f45 44 }
ashleymills 0:04990d454f45 45
ashleymills 0:04990d454f45 46 static inline void
ashleymills 0:04990d454f45 47 dtls_cipher_context_free(dtls_cipher_context_t *ctx) {
ashleymills 0:04990d454f45 48 free(ctx);
ashleymills 0:04990d454f45 49 }
ashleymills 0:04990d454f45 50 #else /* WITH_CONTIKI */
ashleymills 0:04990d454f45 51 MEMB(cipher_storage, dtls_cipher_context_t, DTLS_CIPHER_CONTEXT_MAX);
ashleymills 0:04990d454f45 52
ashleymills 0:04990d454f45 53 static inline dtls_cipher_context_t *
ashleymills 0:04990d454f45 54 dtls_cipher_context_new() {
ashleymills 0:04990d454f45 55 return (dtls_cipher_context_t *)memb_alloc(&cipher_storage);
ashleymills 0:04990d454f45 56 }
ashleymills 0:04990d454f45 57
ashleymills 0:04990d454f45 58 static inline void
ashleymills 0:04990d454f45 59 dtls_cipher_context_free(dtls_cipher_context_t *ctx) {
ashleymills 0:04990d454f45 60 if (ctx)
ashleymills 0:04990d454f45 61 memb_free(&cipher_storage, ctx);
ashleymills 0:04990d454f45 62 }
ashleymills 0:04990d454f45 63 #endif /* WITH_CONTIKI */
ashleymills 0:04990d454f45 64
ashleymills 0:04990d454f45 65 extern void dtls_hmac_storage_init();
ashleymills 0:04990d454f45 66
ashleymills 0:04990d454f45 67 void crypto_init() {
ashleymills 0:04990d454f45 68 dtls_hmac_storage_init();
ashleymills 0:04990d454f45 69
ashleymills 0:04990d454f45 70 #ifdef WITH_CONTIKI
ashleymills 0:04990d454f45 71 memb_init(&cipher_storage);
ashleymills 0:04990d454f45 72 #endif /* WITH_CONTIKI */
ashleymills 0:04990d454f45 73 }
ashleymills 0:04990d454f45 74
ashleymills 0:04990d454f45 75 #ifndef NDEBUG
ashleymills 0:04990d454f45 76 extern void dump(unsigned char *, size_t);
ashleymills 0:04990d454f45 77 #endif
ashleymills 0:04990d454f45 78
ashleymills 0:04990d454f45 79 #define HMAC_UPDATE_SEED(Context,Seed,Length) \
ashleymills 0:04990d454f45 80 if (Seed) dtls_hmac_update(Context, (Seed), (Length))
ashleymills 0:04990d454f45 81
ashleymills 0:04990d454f45 82 size_t
ashleymills 0:04990d454f45 83 dtls_p_hash(dtls_hashfunc_t h,
ashleymills 0:04990d454f45 84 const unsigned char *key, size_t keylen,
ashleymills 0:04990d454f45 85 const unsigned char *label, size_t labellen,
ashleymills 0:04990d454f45 86 const unsigned char *random1, size_t random1len,
ashleymills 0:04990d454f45 87 const unsigned char *random2, size_t random2len,
ashleymills 0:04990d454f45 88 unsigned char *buf, size_t buflen) {
ashleymills 0:04990d454f45 89 dtls_hmac_context_t *hmac_a, *hmac_p;
ashleymills 0:04990d454f45 90
ashleymills 0:04990d454f45 91 unsigned char A[DTLS_HMAC_DIGEST_SIZE];
ashleymills 0:04990d454f45 92 unsigned char tmp[DTLS_HMAC_DIGEST_SIZE];
ashleymills 0:04990d454f45 93 size_t dlen; /* digest length */
ashleymills 0:04990d454f45 94 size_t len = 0; /* result length */
ashleymills 0:04990d454f45 95
ashleymills 0:04990d454f45 96 hmac_a = dtls_hmac_new(key, keylen);
ashleymills 0:04990d454f45 97 if (!hmac_a)
ashleymills 0:04990d454f45 98 return 0;
ashleymills 0:04990d454f45 99
ashleymills 0:04990d454f45 100 /* calculate A(1) from A(0) == seed */
ashleymills 0:04990d454f45 101 HMAC_UPDATE_SEED(hmac_a, label, labellen);
ashleymills 0:04990d454f45 102 HMAC_UPDATE_SEED(hmac_a, random1, random1len);
ashleymills 0:04990d454f45 103 HMAC_UPDATE_SEED(hmac_a, random2, random2len);
ashleymills 0:04990d454f45 104
ashleymills 0:04990d454f45 105 dlen = dtls_hmac_finalize(hmac_a, A);
ashleymills 0:04990d454f45 106
ashleymills 0:04990d454f45 107 hmac_p = dtls_hmac_new(key, keylen);
ashleymills 0:04990d454f45 108 if (!hmac_p)
ashleymills 0:04990d454f45 109 goto error;
ashleymills 0:04990d454f45 110
ashleymills 0:04990d454f45 111 while (len + dlen < buflen) {
ashleymills 0:04990d454f45 112
ashleymills 0:04990d454f45 113 /* FIXME: rewrite loop to avoid superflous call to dtls_hmac_init() */
ashleymills 0:04990d454f45 114 dtls_hmac_init(hmac_p, key, keylen);
ashleymills 0:04990d454f45 115 dtls_hmac_update(hmac_p, A, dlen);
ashleymills 0:04990d454f45 116
ashleymills 0:04990d454f45 117 HMAC_UPDATE_SEED(hmac_p, label, labellen);
ashleymills 0:04990d454f45 118 HMAC_UPDATE_SEED(hmac_p, random1, random1len);
ashleymills 0:04990d454f45 119 HMAC_UPDATE_SEED(hmac_p, random2, random2len);
ashleymills 0:04990d454f45 120
ashleymills 0:04990d454f45 121 len += dtls_hmac_finalize(hmac_p, tmp);
ashleymills 0:04990d454f45 122 memcpy(buf, tmp, dlen);
ashleymills 0:04990d454f45 123 buf += dlen;
ashleymills 0:04990d454f45 124
ashleymills 0:04990d454f45 125 /* calculate A(i+1) */
ashleymills 0:04990d454f45 126 dtls_hmac_init(hmac_a, key, keylen);
ashleymills 0:04990d454f45 127 dtls_hmac_update(hmac_a, A, dlen);
ashleymills 0:04990d454f45 128 dtls_hmac_finalize(hmac_a, A);
ashleymills 0:04990d454f45 129 }
ashleymills 0:04990d454f45 130
ashleymills 0:04990d454f45 131 dtls_hmac_init(hmac_p, key, keylen);
ashleymills 0:04990d454f45 132 dtls_hmac_update(hmac_p, A, dlen);
ashleymills 0:04990d454f45 133
ashleymills 0:04990d454f45 134 HMAC_UPDATE_SEED(hmac_p, label, labellen);
ashleymills 0:04990d454f45 135 HMAC_UPDATE_SEED(hmac_p, random1, random1len);
ashleymills 0:04990d454f45 136 HMAC_UPDATE_SEED(hmac_p, random2, random2len);
ashleymills 0:04990d454f45 137
ashleymills 0:04990d454f45 138 dtls_hmac_finalize(hmac_p, tmp);
ashleymills 0:04990d454f45 139 memcpy(buf, tmp, buflen - len);
ashleymills 0:04990d454f45 140
ashleymills 0:04990d454f45 141 error:
ashleymills 0:04990d454f45 142 dtls_hmac_free(hmac_a);
ashleymills 0:04990d454f45 143 dtls_hmac_free(hmac_p);
ashleymills 0:04990d454f45 144
ashleymills 0:04990d454f45 145 return buflen;
ashleymills 0:04990d454f45 146 }
ashleymills 0:04990d454f45 147
ashleymills 0:04990d454f45 148 size_t
ashleymills 0:04990d454f45 149 dtls_prf(const unsigned char *key, size_t keylen,
ashleymills 0:04990d454f45 150 const unsigned char *label, size_t labellen,
ashleymills 0:04990d454f45 151 const unsigned char *random1, size_t random1len,
ashleymills 0:04990d454f45 152 const unsigned char *random2, size_t random2len,
ashleymills 0:04990d454f45 153 unsigned char *buf, size_t buflen) {
ashleymills 0:04990d454f45 154
ashleymills 0:04990d454f45 155 /* Clear the result buffer */
ashleymills 0:04990d454f45 156 memset(buf, 0, buflen);
ashleymills 0:04990d454f45 157 return dtls_p_hash(HASH_SHA256,
ashleymills 0:04990d454f45 158 key, keylen,
ashleymills 0:04990d454f45 159 label, labellen,
ashleymills 0:04990d454f45 160 random1, random1len,
ashleymills 0:04990d454f45 161 random2, random2len,
ashleymills 0:04990d454f45 162 buf, buflen);
ashleymills 0:04990d454f45 163 }
ashleymills 0:04990d454f45 164
ashleymills 0:04990d454f45 165 void
ashleymills 0:04990d454f45 166 dtls_mac(dtls_hmac_context_t *hmac_ctx,
ashleymills 0:04990d454f45 167 const unsigned char *record,
ashleymills 0:04990d454f45 168 const unsigned char *packet, size_t length,
ashleymills 0:04990d454f45 169 unsigned char *buf) {
ashleymills 0:04990d454f45 170 uint16 L;
ashleymills 0:04990d454f45 171 dtls_int_to_uint16(L, length);
ashleymills 0:04990d454f45 172
ashleymills 0:04990d454f45 173 assert(hmac_ctx);
ashleymills 0:04990d454f45 174 dtls_hmac_update(hmac_ctx, record +3, sizeof(uint16) + sizeof(uint48));
ashleymills 0:04990d454f45 175 dtls_hmac_update(hmac_ctx, record, sizeof(uint8) + sizeof(uint16));
ashleymills 0:04990d454f45 176 dtls_hmac_update(hmac_ctx, L, sizeof(uint16));
ashleymills 0:04990d454f45 177 dtls_hmac_update(hmac_ctx, packet, length);
ashleymills 0:04990d454f45 178
ashleymills 0:04990d454f45 179 dtls_hmac_finalize(hmac_ctx, buf);
ashleymills 0:04990d454f45 180 }
ashleymills 0:04990d454f45 181
ashleymills 0:04990d454f45 182 static inline void
ashleymills 0:04990d454f45 183 dtls_ccm_init(aes128_ccm_t *ccm_ctx, unsigned char *N, size_t length) {
ashleymills 0:04990d454f45 184 assert(ccm_ctx);
ashleymills 0:04990d454f45 185
ashleymills 0:04990d454f45 186 if (length < DTLS_CCM_BLOCKSIZE)
ashleymills 0:04990d454f45 187 memset(ccm_ctx->N + length, 0, DTLS_CCM_BLOCKSIZE - length);
ashleymills 0:04990d454f45 188
ashleymills 0:04990d454f45 189 memcpy(ccm_ctx->N, N, DTLS_CCM_BLOCKSIZE);
ashleymills 0:04990d454f45 190 }
ashleymills 0:04990d454f45 191
ashleymills 0:04990d454f45 192 size_t
ashleymills 0:04990d454f45 193 dtls_ccm_encrypt(aes128_ccm_t *ccm_ctx, const unsigned char *src, size_t srclen,
ashleymills 0:04990d454f45 194 unsigned char *buf,
ashleymills 0:04990d454f45 195 const unsigned char *aad, size_t la) {
ashleymills 0:04990d454f45 196 long int len;
ashleymills 0:04990d454f45 197
ashleymills 0:04990d454f45 198 assert(ccm_ctx);
ashleymills 0:04990d454f45 199
ashleymills 0:04990d454f45 200 len = dtls_ccm_encrypt_message(&ccm_ctx->ctx, 8 /* M */,
ashleymills 0:04990d454f45 201 max(2, 15 - DTLS_CCM_NONCE_SIZE),
ashleymills 0:04990d454f45 202 ccm_ctx->N,
ashleymills 0:04990d454f45 203 buf, srclen,
ashleymills 0:04990d454f45 204 aad, la);
ashleymills 0:04990d454f45 205 return len;
ashleymills 0:04990d454f45 206 }
ashleymills 0:04990d454f45 207
ashleymills 0:04990d454f45 208 size_t
ashleymills 0:04990d454f45 209 dtls_ccm_decrypt(aes128_ccm_t *ccm_ctx, const unsigned char *src,
ashleymills 0:04990d454f45 210 size_t srclen, unsigned char *buf,
ashleymills 0:04990d454f45 211 const unsigned char *aad, size_t la) {
ashleymills 0:04990d454f45 212 long int len;
ashleymills 0:04990d454f45 213
ashleymills 0:04990d454f45 214 assert(ccm_ctx);
ashleymills 0:04990d454f45 215
ashleymills 0:04990d454f45 216 len = dtls_ccm_decrypt_message(&ccm_ctx->ctx, 8 /* M */,
ashleymills 0:04990d454f45 217 max(2, 15 - DTLS_CCM_NONCE_SIZE),
ashleymills 0:04990d454f45 218 ccm_ctx->N,
ashleymills 0:04990d454f45 219 buf, srclen,
ashleymills 0:04990d454f45 220 aad, la);
ashleymills 0:04990d454f45 221 return len;
ashleymills 0:04990d454f45 222 }
ashleymills 0:04990d454f45 223
ashleymills 0:04990d454f45 224 size_t
ashleymills 0:04990d454f45 225 dtls_pre_master_secret(unsigned char *key, size_t keylen,
ashleymills 0:04990d454f45 226 unsigned char *result) {
ashleymills 0:04990d454f45 227 unsigned char *p = result;
ashleymills 0:04990d454f45 228
ashleymills 0:04990d454f45 229 dtls_int_to_uint16(p, keylen);
ashleymills 0:04990d454f45 230 p += sizeof(uint16);
ashleymills 0:04990d454f45 231
ashleymills 0:04990d454f45 232 memset(p, 0, keylen);
ashleymills 0:04990d454f45 233 p += keylen;
ashleymills 0:04990d454f45 234
ashleymills 0:04990d454f45 235 memcpy(p, result, sizeof(uint16));
ashleymills 0:04990d454f45 236 p += sizeof(uint16);
ashleymills 0:04990d454f45 237
ashleymills 0:04990d454f45 238 memcpy(p, key, keylen);
ashleymills 0:04990d454f45 239
ashleymills 0:04990d454f45 240 return (sizeof(uint16) + keylen) << 1;
ashleymills 0:04990d454f45 241 }
ashleymills 0:04990d454f45 242
ashleymills 0:04990d454f45 243 void
ashleymills 0:04990d454f45 244 dtls_cipher_set_iv(dtls_cipher_context_t *ctx,
ashleymills 0:04990d454f45 245 unsigned char *iv, size_t length) {
ashleymills 0:04990d454f45 246 assert(ctx);
ashleymills 0:04990d454f45 247 dtls_ccm_init(&ctx->data, iv, length);
ashleymills 0:04990d454f45 248 }
ashleymills 0:04990d454f45 249
ashleymills 0:04990d454f45 250 dtls_cipher_context_t *
ashleymills 0:04990d454f45 251 dtls_cipher_new(dtls_cipher_t cipher,
ashleymills 0:04990d454f45 252 unsigned char *key, size_t keylen) {
ashleymills 0:04990d454f45 253 dtls_cipher_context_t *cipher_context = NULL;
ashleymills 0:04990d454f45 254
ashleymills 0:04990d454f45 255 cipher_context = dtls_cipher_context_new();
ashleymills 0:04990d454f45 256 if (!cipher_context) {
ashleymills 0:04990d454f45 257 warn2("cannot allocate cipher_context\r\n");
ashleymills 0:04990d454f45 258 return NULL;
ashleymills 0:04990d454f45 259 }
ashleymills 0:04990d454f45 260
ashleymills 0:04990d454f45 261 switch (cipher) {
ashleymills 0:04990d454f45 262 case TLS_PSK_WITH_AES_128_CCM_8: {
ashleymills 0:04990d454f45 263 aes128_ccm_t *ccm_ctx = &cipher_context->data;
ashleymills 0:04990d454f45 264
ashleymills 0:04990d454f45 265 if (rijndael_set_key_enc_only(&ccm_ctx->ctx, key, 8 * keylen) < 0) {
ashleymills 0:04990d454f45 266 /* cleanup everything in case the key has the wrong size */
ashleymills 0:04990d454f45 267 warn2("cannot set rijndael key\n");
ashleymills 0:04990d454f45 268 goto error;
ashleymills 0:04990d454f45 269 }
ashleymills 0:04990d454f45 270 break;
ashleymills 0:04990d454f45 271 }
ashleymills 0:04990d454f45 272 default:
ashleymills 0:04990d454f45 273 warn2("unknown cipher %04x\n", cipher);
ashleymills 0:04990d454f45 274 goto error;
ashleymills 0:04990d454f45 275 }
ashleymills 0:04990d454f45 276
ashleymills 0:04990d454f45 277 return cipher_context;
ashleymills 0:04990d454f45 278 error:
ashleymills 0:04990d454f45 279 dtls_cipher_context_free(cipher_context);
ashleymills 0:04990d454f45 280 return NULL;
ashleymills 0:04990d454f45 281 }
ashleymills 0:04990d454f45 282
ashleymills 0:04990d454f45 283 void
ashleymills 0:04990d454f45 284 dtls_cipher_free(dtls_cipher_context_t *cipher_context) {
ashleymills 0:04990d454f45 285 dtls_cipher_context_free(cipher_context);
ashleymills 0:04990d454f45 286 }
ashleymills 0:04990d454f45 287
ashleymills 0:04990d454f45 288 int
ashleymills 0:04990d454f45 289 dtls_encrypt(dtls_cipher_context_t *ctx,
ashleymills 0:04990d454f45 290 const unsigned char *src, size_t length,
ashleymills 0:04990d454f45 291 unsigned char *buf,
ashleymills 0:04990d454f45 292 const unsigned char *aad, size_t la) {
ashleymills 0:04990d454f45 293 if (ctx) {
ashleymills 0:04990d454f45 294 if (src != buf)
ashleymills 0:04990d454f45 295 memmove(buf, src, length);
ashleymills 0:04990d454f45 296 return dtls_ccm_encrypt(&ctx->data, src, length, buf,
ashleymills 0:04990d454f45 297 aad, la);
ashleymills 0:04990d454f45 298 }
ashleymills 0:04990d454f45 299
ashleymills 0:04990d454f45 300 return -1;
ashleymills 0:04990d454f45 301 }
ashleymills 0:04990d454f45 302
ashleymills 0:04990d454f45 303 int
ashleymills 0:04990d454f45 304 dtls_decrypt(dtls_cipher_context_t *ctx,
ashleymills 0:04990d454f45 305 const unsigned char *src, size_t length,
ashleymills 0:04990d454f45 306 unsigned char *buf,
ashleymills 0:04990d454f45 307 const unsigned char *aad, size_t la) {
ashleymills 0:04990d454f45 308 if (ctx) {
ashleymills 0:04990d454f45 309 if (src != buf)
ashleymills 0:04990d454f45 310 memmove(buf, src, length);
ashleymills 0:04990d454f45 311 return dtls_ccm_decrypt(&ctx->data, src, length, buf,
ashleymills 0:04990d454f45 312 aad, la);
ashleymills 0:04990d454f45 313 }
ashleymills 0:04990d454f45 314
ashleymills 0:04990d454f45 315 return -1;
ashleymills 0:04990d454f45 316 }
ashleymills 0:04990d454f45 317