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 <stdio.h>
ashleymills 0:ff9ebe0cf0e9 28 #ifdef HAVE_ASSERT_H
ashleymills 0:ff9ebe0cf0e9 29 #include <assert.h>
ashleymills 0:ff9ebe0cf0e9 30 #endif
ashleymills 0:ff9ebe0cf0e9 31
ashleymills 0:ff9ebe0cf0e9 32 #include "global.h"
ashleymills 0:ff9ebe0cf0e9 33 #include "debug.h"
ashleymills 0:ff9ebe0cf0e9 34 #include "numeric.h"
ashleymills 0:ff9ebe0cf0e9 35 #include "dtls.h"
ashleymills 0:ff9ebe0cf0e9 36 #include "crypto.h"
ashleymills 0:ff9ebe0cf0e9 37 #include "ccm.h"
ashleymills 0:ff9ebe0cf0e9 38 #include "ecc/ecc.h"
ashleymills 0:ff9ebe0cf0e9 39
ashleymills 0:ff9ebe0cf0e9 40 #ifndef WITH_CONTIKI
ashleymills 0:ff9ebe0cf0e9 41 #include <stdlib.h>
ashleymills 0:ff9ebe0cf0e9 42
ashleymills 0:ff9ebe0cf0e9 43 #define __DEBUG__ 4
ashleymills 0:ff9ebe0cf0e9 44 #ifndef __MODULE__
ashleymills 0:ff9ebe0cf0e9 45 #define __MODULE__ "crypto.c"
ashleymills 0:ff9ebe0cf0e9 46 #endif
ashleymills 0:ff9ebe0cf0e9 47 #include "dbg.h"
ashleymills 0:ff9ebe0cf0e9 48
ashleymills 0:ff9ebe0cf0e9 49 static inline dtls_cipher_context_t *
ashleymills 0:ff9ebe0cf0e9 50 dtls_cipher_context_new() {
ashleymills 0:ff9ebe0cf0e9 51 return (dtls_cipher_context_t *)malloc(sizeof(dtls_cipher_context_t));
ashleymills 0:ff9ebe0cf0e9 52 }
ashleymills 0:ff9ebe0cf0e9 53
ashleymills 0:ff9ebe0cf0e9 54 static inline void
ashleymills 0:ff9ebe0cf0e9 55 dtls_cipher_context_free(dtls_cipher_context_t *ctx) {
ashleymills 0:ff9ebe0cf0e9 56 free(ctx);
ashleymills 0:ff9ebe0cf0e9 57 }
ashleymills 0:ff9ebe0cf0e9 58 #else /* WITH_CONTIKI */
ashleymills 0:ff9ebe0cf0e9 59 MEMB(cipher_storage, dtls_cipher_context_t, DTLS_CIPHER_CONTEXT_MAX);
ashleymills 0:ff9ebe0cf0e9 60
ashleymills 0:ff9ebe0cf0e9 61 static inline dtls_cipher_context_t *
ashleymills 0:ff9ebe0cf0e9 62 dtls_cipher_context_new() {
ashleymills 0:ff9ebe0cf0e9 63 return (dtls_cipher_context_t *)memb_alloc(&cipher_storage);
ashleymills 0:ff9ebe0cf0e9 64 }
ashleymills 0:ff9ebe0cf0e9 65
ashleymills 0:ff9ebe0cf0e9 66 static inline void
ashleymills 0:ff9ebe0cf0e9 67 dtls_cipher_context_free(dtls_cipher_context_t *ctx) {
ashleymills 0:ff9ebe0cf0e9 68 if (ctx)
ashleymills 0:ff9ebe0cf0e9 69 memb_free(&cipher_storage, ctx);
ashleymills 0:ff9ebe0cf0e9 70 }
ashleymills 0:ff9ebe0cf0e9 71 #endif /* WITH_CONTIKI */
ashleymills 0:ff9ebe0cf0e9 72
ashleymills 0:ff9ebe0cf0e9 73 void crypto_init() {
ashleymills 0:ff9ebe0cf0e9 74 dtls_hmac_storage_init();
ashleymills 0:ff9ebe0cf0e9 75
ashleymills 0:ff9ebe0cf0e9 76 #ifdef WITH_CONTIKI
ashleymills 0:ff9ebe0cf0e9 77 memb_init(&cipher_storage);
ashleymills 0:ff9ebe0cf0e9 78 #endif /* WITH_CONTIKI */
ashleymills 0:ff9ebe0cf0e9 79 }
ashleymills 0:ff9ebe0cf0e9 80
ashleymills 0:ff9ebe0cf0e9 81 #define HMAC_UPDATE_SEED(Context,Seed,Length) \
ashleymills 0:ff9ebe0cf0e9 82 if (Seed) dtls_hmac_update(Context, (Seed), (Length))
ashleymills 0:ff9ebe0cf0e9 83
ashleymills 0:ff9ebe0cf0e9 84 size_t
ashleymills 0:ff9ebe0cf0e9 85 dtls_p_hash(dtls_hashfunc_t h,
ashleymills 0:ff9ebe0cf0e9 86 const unsigned char *key, size_t keylen,
ashleymills 0:ff9ebe0cf0e9 87 const unsigned char *label, size_t labellen,
ashleymills 0:ff9ebe0cf0e9 88 const unsigned char *random1, size_t random1len,
ashleymills 0:ff9ebe0cf0e9 89 const unsigned char *random2, size_t random2len,
ashleymills 0:ff9ebe0cf0e9 90 unsigned char *buf, size_t buflen) {
ashleymills 0:ff9ebe0cf0e9 91 dtls_hmac_context_t *hmac_a, *hmac_p;
ashleymills 0:ff9ebe0cf0e9 92
ashleymills 0:ff9ebe0cf0e9 93 unsigned char A[DTLS_HMAC_DIGEST_SIZE];
ashleymills 0:ff9ebe0cf0e9 94 unsigned char tmp[DTLS_HMAC_DIGEST_SIZE];
ashleymills 0:ff9ebe0cf0e9 95 size_t dlen; /* digest length */
ashleymills 0:ff9ebe0cf0e9 96 size_t len = 0; /* result length */
ashleymills 0:ff9ebe0cf0e9 97
ashleymills 0:ff9ebe0cf0e9 98 hmac_a = dtls_hmac_new(key, keylen);
ashleymills 0:ff9ebe0cf0e9 99 if (!hmac_a)
ashleymills 0:ff9ebe0cf0e9 100 return 0;
ashleymills 0:ff9ebe0cf0e9 101
ashleymills 0:ff9ebe0cf0e9 102 /* calculate A(1) from A(0) == seed */
ashleymills 0:ff9ebe0cf0e9 103 HMAC_UPDATE_SEED(hmac_a, label, labellen);
ashleymills 0:ff9ebe0cf0e9 104 HMAC_UPDATE_SEED(hmac_a, random1, random1len);
ashleymills 0:ff9ebe0cf0e9 105 HMAC_UPDATE_SEED(hmac_a, random2, random2len);
ashleymills 0:ff9ebe0cf0e9 106
ashleymills 0:ff9ebe0cf0e9 107 dlen = dtls_hmac_finalize(hmac_a, A);
ashleymills 0:ff9ebe0cf0e9 108
ashleymills 0:ff9ebe0cf0e9 109 hmac_p = dtls_hmac_new(key, keylen);
ashleymills 0:ff9ebe0cf0e9 110 if (!hmac_p)
ashleymills 0:ff9ebe0cf0e9 111 goto error;
ashleymills 0:ff9ebe0cf0e9 112
ashleymills 0:ff9ebe0cf0e9 113 while (len + dlen < buflen) {
ashleymills 0:ff9ebe0cf0e9 114
ashleymills 0:ff9ebe0cf0e9 115 /* FIXME: rewrite loop to avoid superflous call to dtls_hmac_init() */
ashleymills 0:ff9ebe0cf0e9 116 dtls_hmac_init(hmac_p, key, keylen);
ashleymills 0:ff9ebe0cf0e9 117 dtls_hmac_update(hmac_p, A, dlen);
ashleymills 0:ff9ebe0cf0e9 118
ashleymills 0:ff9ebe0cf0e9 119 HMAC_UPDATE_SEED(hmac_p, label, labellen);
ashleymills 0:ff9ebe0cf0e9 120 HMAC_UPDATE_SEED(hmac_p, random1, random1len);
ashleymills 0:ff9ebe0cf0e9 121 HMAC_UPDATE_SEED(hmac_p, random2, random2len);
ashleymills 0:ff9ebe0cf0e9 122
ashleymills 0:ff9ebe0cf0e9 123 len += dtls_hmac_finalize(hmac_p, tmp);
ashleymills 0:ff9ebe0cf0e9 124 memcpy(buf, tmp, dlen);
ashleymills 0:ff9ebe0cf0e9 125 buf += dlen;
ashleymills 0:ff9ebe0cf0e9 126
ashleymills 0:ff9ebe0cf0e9 127 /* calculate A(i+1) */
ashleymills 0:ff9ebe0cf0e9 128 dtls_hmac_init(hmac_a, key, keylen);
ashleymills 0:ff9ebe0cf0e9 129 dtls_hmac_update(hmac_a, A, dlen);
ashleymills 0:ff9ebe0cf0e9 130 dtls_hmac_finalize(hmac_a, A);
ashleymills 0:ff9ebe0cf0e9 131 }
ashleymills 0:ff9ebe0cf0e9 132
ashleymills 0:ff9ebe0cf0e9 133 dtls_hmac_init(hmac_p, key, keylen);
ashleymills 0:ff9ebe0cf0e9 134 dtls_hmac_update(hmac_p, A, dlen);
ashleymills 0:ff9ebe0cf0e9 135
ashleymills 0:ff9ebe0cf0e9 136 HMAC_UPDATE_SEED(hmac_p, label, labellen);
ashleymills 0:ff9ebe0cf0e9 137 HMAC_UPDATE_SEED(hmac_p, random1, random1len);
ashleymills 0:ff9ebe0cf0e9 138 HMAC_UPDATE_SEED(hmac_p, random2, random2len);
ashleymills 0:ff9ebe0cf0e9 139
ashleymills 0:ff9ebe0cf0e9 140 dtls_hmac_finalize(hmac_p, tmp);
ashleymills 0:ff9ebe0cf0e9 141 memcpy(buf, tmp, buflen - len);
ashleymills 0:ff9ebe0cf0e9 142
ashleymills 0:ff9ebe0cf0e9 143 error:
ashleymills 0:ff9ebe0cf0e9 144 dtls_hmac_free(hmac_a);
ashleymills 0:ff9ebe0cf0e9 145 dtls_hmac_free(hmac_p);
ashleymills 0:ff9ebe0cf0e9 146
ashleymills 0:ff9ebe0cf0e9 147 return buflen;
ashleymills 0:ff9ebe0cf0e9 148 }
ashleymills 0:ff9ebe0cf0e9 149
ashleymills 0:ff9ebe0cf0e9 150 size_t
ashleymills 0:ff9ebe0cf0e9 151 dtls_prf(const unsigned char *key, size_t keylen,
ashleymills 0:ff9ebe0cf0e9 152 const unsigned char *label, size_t labellen,
ashleymills 0:ff9ebe0cf0e9 153 const unsigned char *random1, size_t random1len,
ashleymills 0:ff9ebe0cf0e9 154 const unsigned char *random2, size_t random2len,
ashleymills 0:ff9ebe0cf0e9 155 unsigned char *buf, size_t buflen) {
ashleymills 0:ff9ebe0cf0e9 156
ashleymills 0:ff9ebe0cf0e9 157 /* Clear the result buffer */
ashleymills 0:ff9ebe0cf0e9 158 memset(buf, 0, buflen);
ashleymills 0:ff9ebe0cf0e9 159 return dtls_p_hash(HASH_SHA256,
ashleymills 0:ff9ebe0cf0e9 160 key, keylen,
ashleymills 0:ff9ebe0cf0e9 161 label, labellen,
ashleymills 0:ff9ebe0cf0e9 162 random1, random1len,
ashleymills 0:ff9ebe0cf0e9 163 random2, random2len,
ashleymills 0:ff9ebe0cf0e9 164 buf, buflen);
ashleymills 0:ff9ebe0cf0e9 165 }
ashleymills 0:ff9ebe0cf0e9 166
ashleymills 0:ff9ebe0cf0e9 167 void
ashleymills 0:ff9ebe0cf0e9 168 dtls_mac(dtls_hmac_context_t *hmac_ctx,
ashleymills 0:ff9ebe0cf0e9 169 const unsigned char *record,
ashleymills 0:ff9ebe0cf0e9 170 const unsigned char *packet, size_t length,
ashleymills 0:ff9ebe0cf0e9 171 unsigned char *buf) {
ashleymills 0:ff9ebe0cf0e9 172 uint16 L;
ashleymills 0:ff9ebe0cf0e9 173 dtls_int_to_uint16(L, length);
ashleymills 0:ff9ebe0cf0e9 174
ashleymills 0:ff9ebe0cf0e9 175 assert(hmac_ctx);
ashleymills 0:ff9ebe0cf0e9 176 dtls_hmac_update(hmac_ctx, record +3, sizeof(uint16) + sizeof(uint48));
ashleymills 0:ff9ebe0cf0e9 177 dtls_hmac_update(hmac_ctx, record, sizeof(uint8) + sizeof(uint16));
ashleymills 0:ff9ebe0cf0e9 178 dtls_hmac_update(hmac_ctx, L, sizeof(uint16));
ashleymills 0:ff9ebe0cf0e9 179 dtls_hmac_update(hmac_ctx, packet, length);
ashleymills 0:ff9ebe0cf0e9 180
ashleymills 0:ff9ebe0cf0e9 181 dtls_hmac_finalize(hmac_ctx, buf);
ashleymills 0:ff9ebe0cf0e9 182 }
ashleymills 0:ff9ebe0cf0e9 183
ashleymills 0:ff9ebe0cf0e9 184 static size_t
ashleymills 0:ff9ebe0cf0e9 185 dtls_ccm_encrypt(aes128_ccm_t *ccm_ctx, const unsigned char *src, size_t srclen,
ashleymills 0:ff9ebe0cf0e9 186 unsigned char *buf,
ashleymills 0:ff9ebe0cf0e9 187 unsigned char *nounce,
ashleymills 0:ff9ebe0cf0e9 188 const unsigned char *aad, size_t la) {
ashleymills 0:ff9ebe0cf0e9 189 long int len;
ashleymills 0:ff9ebe0cf0e9 190
ashleymills 0:ff9ebe0cf0e9 191 assert(ccm_ctx);
ashleymills 0:ff9ebe0cf0e9 192
ashleymills 0:ff9ebe0cf0e9 193 len = dtls_ccm_encrypt_message(&ccm_ctx->ctx, 8 /* M */,
ashleymills 0:ff9ebe0cf0e9 194 max(2, 15 - DTLS_CCM_NONCE_SIZE),
ashleymills 0:ff9ebe0cf0e9 195 nounce,
ashleymills 0:ff9ebe0cf0e9 196 buf, srclen,
ashleymills 0:ff9ebe0cf0e9 197 aad, la);
ashleymills 0:ff9ebe0cf0e9 198 return len;
ashleymills 0:ff9ebe0cf0e9 199 }
ashleymills 0:ff9ebe0cf0e9 200
ashleymills 0:ff9ebe0cf0e9 201 static size_t
ashleymills 0:ff9ebe0cf0e9 202 dtls_ccm_decrypt(aes128_ccm_t *ccm_ctx, const unsigned char *src,
ashleymills 0:ff9ebe0cf0e9 203 size_t srclen, unsigned char *buf,
ashleymills 0:ff9ebe0cf0e9 204 unsigned char *nounce,
ashleymills 0:ff9ebe0cf0e9 205 const unsigned char *aad, size_t la) {
ashleymills 0:ff9ebe0cf0e9 206 long int len;
ashleymills 0:ff9ebe0cf0e9 207
ashleymills 0:ff9ebe0cf0e9 208 assert(ccm_ctx);
ashleymills 0:ff9ebe0cf0e9 209
ashleymills 0:ff9ebe0cf0e9 210 len = dtls_ccm_decrypt_message(&ccm_ctx->ctx, 8 /* M */,
ashleymills 0:ff9ebe0cf0e9 211 max(2, 15 - DTLS_CCM_NONCE_SIZE),
ashleymills 0:ff9ebe0cf0e9 212 nounce,
ashleymills 0:ff9ebe0cf0e9 213 buf, srclen,
ashleymills 0:ff9ebe0cf0e9 214 aad, la);
ashleymills 0:ff9ebe0cf0e9 215 return len;
ashleymills 0:ff9ebe0cf0e9 216 }
ashleymills 0:ff9ebe0cf0e9 217
ashleymills 0:ff9ebe0cf0e9 218 size_t
ashleymills 0:ff9ebe0cf0e9 219 dtls_psk_pre_master_secret(unsigned char *key, size_t keylen,
ashleymills 0:ff9ebe0cf0e9 220 unsigned char *result) {
ashleymills 0:ff9ebe0cf0e9 221 unsigned char *p = result;
ashleymills 0:ff9ebe0cf0e9 222
ashleymills 0:ff9ebe0cf0e9 223 dtls_int_to_uint16(p, keylen);
ashleymills 0:ff9ebe0cf0e9 224 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 225
ashleymills 0:ff9ebe0cf0e9 226 memset(p, 0, keylen);
ashleymills 0:ff9ebe0cf0e9 227 p += keylen;
ashleymills 0:ff9ebe0cf0e9 228
ashleymills 0:ff9ebe0cf0e9 229 memcpy(p, result, sizeof(uint16));
ashleymills 0:ff9ebe0cf0e9 230 p += sizeof(uint16);
ashleymills 0:ff9ebe0cf0e9 231
ashleymills 0:ff9ebe0cf0e9 232 memcpy(p, key, keylen);
ashleymills 0:ff9ebe0cf0e9 233
ashleymills 0:ff9ebe0cf0e9 234 return (sizeof(uint16) + keylen) << 1;
ashleymills 0:ff9ebe0cf0e9 235 }
ashleymills 0:ff9ebe0cf0e9 236
ashleymills 0:ff9ebe0cf0e9 237 static void dtls_ec_key_to_uint32(const unsigned char *key, size_t key_size,
ashleymills 0:ff9ebe0cf0e9 238 uint32_t *result) {
ashleymills 0:ff9ebe0cf0e9 239 int i;
ashleymills 0:ff9ebe0cf0e9 240
ashleymills 0:ff9ebe0cf0e9 241 for (i = (key_size / sizeof(uint32_t)) - 1; i >= 0 ; i--) {
ashleymills 0:ff9ebe0cf0e9 242 *result = dtls_uint32_to_int(&key[i * sizeof(uint32_t)]);
ashleymills 0:ff9ebe0cf0e9 243 result++;
ashleymills 0:ff9ebe0cf0e9 244 }
ashleymills 0:ff9ebe0cf0e9 245 }
ashleymills 0:ff9ebe0cf0e9 246
ashleymills 0:ff9ebe0cf0e9 247 static void dtls_ec_key_from_uint32(const uint32_t *key, size_t key_size,
ashleymills 0:ff9ebe0cf0e9 248 unsigned char *result) {
ashleymills 0:ff9ebe0cf0e9 249 int i;
ashleymills 0:ff9ebe0cf0e9 250
ashleymills 0:ff9ebe0cf0e9 251 for (i = (key_size / sizeof(uint32_t)) - 1; i >= 0 ; i--) {
ashleymills 0:ff9ebe0cf0e9 252 dtls_int_to_uint32(result, key[i]);
ashleymills 0:ff9ebe0cf0e9 253 result += 4;
ashleymills 0:ff9ebe0cf0e9 254 }
ashleymills 0:ff9ebe0cf0e9 255 }
ashleymills 0:ff9ebe0cf0e9 256
ashleymills 0:ff9ebe0cf0e9 257 int dtls_ec_key_from_uint32_asn1(const uint32_t *key, size_t key_size,
ashleymills 0:ff9ebe0cf0e9 258 unsigned char *buf) {
ashleymills 0:ff9ebe0cf0e9 259 int i;
ashleymills 0:ff9ebe0cf0e9 260 unsigned char *buf_orig = buf;
ashleymills 0:ff9ebe0cf0e9 261 int first = 1;
ashleymills 0:ff9ebe0cf0e9 262
ashleymills 0:ff9ebe0cf0e9 263 for (i = (key_size / sizeof(uint32_t)) - 1; i >= 0 ; i--) {
ashleymills 0:ff9ebe0cf0e9 264 if (key[i] == 0)
ashleymills 0:ff9ebe0cf0e9 265 continue;
ashleymills 0:ff9ebe0cf0e9 266 /* the first bit has to be set to zero, to indicate a poritive integer */
ashleymills 0:ff9ebe0cf0e9 267 if (first && key[i] & 0x80000000) {
ashleymills 0:ff9ebe0cf0e9 268 *buf = 0;
ashleymills 0:ff9ebe0cf0e9 269 buf++;
ashleymills 0:ff9ebe0cf0e9 270 dtls_int_to_uint32(buf, key[i]);
ashleymills 0:ff9ebe0cf0e9 271 buf += 4;
ashleymills 0:ff9ebe0cf0e9 272 } else if (first && !(key[i] & 0xFF800000)) {
ashleymills 0:ff9ebe0cf0e9 273 buf[0] = (key[i] >> 16) & 0xff;
ashleymills 0:ff9ebe0cf0e9 274 buf[1] = (key[i] >> 8) & 0xff;
ashleymills 0:ff9ebe0cf0e9 275 buf[2] = key[i] & 0xff;
ashleymills 0:ff9ebe0cf0e9 276 buf += 3;
ashleymills 0:ff9ebe0cf0e9 277 } else if (first && !(key[i] & 0xFFFF8000)) {
ashleymills 0:ff9ebe0cf0e9 278 buf[0] = (key[i] >> 8) & 0xff;
ashleymills 0:ff9ebe0cf0e9 279 buf[1] = key[i] & 0xff;
ashleymills 0:ff9ebe0cf0e9 280 buf += 2;
ashleymills 0:ff9ebe0cf0e9 281 } else if (first && !(key[i] & 0xFFFFFF80)) {
ashleymills 0:ff9ebe0cf0e9 282 buf[0] = key[i] & 0xff;
ashleymills 0:ff9ebe0cf0e9 283 buf += 1;
ashleymills 0:ff9ebe0cf0e9 284 } else {
ashleymills 0:ff9ebe0cf0e9 285 dtls_int_to_uint32(buf, key[i]);
ashleymills 0:ff9ebe0cf0e9 286 buf += 4;
ashleymills 0:ff9ebe0cf0e9 287 }
ashleymills 0:ff9ebe0cf0e9 288 first = 0;
ashleymills 0:ff9ebe0cf0e9 289 }
ashleymills 0:ff9ebe0cf0e9 290 return buf - buf_orig;
ashleymills 0:ff9ebe0cf0e9 291 }
ashleymills 0:ff9ebe0cf0e9 292
ashleymills 0:ff9ebe0cf0e9 293 size_t dtls_ecdh_pre_master_secret(unsigned char *priv_key,
ashleymills 0:ff9ebe0cf0e9 294 unsigned char *pub_key_x,
ashleymills 0:ff9ebe0cf0e9 295 unsigned char *pub_key_y,
ashleymills 0:ff9ebe0cf0e9 296 size_t key_size,
ashleymills 0:ff9ebe0cf0e9 297 unsigned char *result) {
ashleymills 0:ff9ebe0cf0e9 298 uint32_t priv[8];
ashleymills 0:ff9ebe0cf0e9 299 uint32_t pub_x[8];
ashleymills 0:ff9ebe0cf0e9 300 uint32_t pub_y[8];
ashleymills 0:ff9ebe0cf0e9 301 uint32_t result_x[8];
ashleymills 0:ff9ebe0cf0e9 302 uint32_t result_y[8];
ashleymills 0:ff9ebe0cf0e9 303
ashleymills 0:ff9ebe0cf0e9 304 dtls_ec_key_to_uint32(priv_key, key_size, priv);
ashleymills 0:ff9ebe0cf0e9 305 dtls_ec_key_to_uint32(pub_key_x, key_size, pub_x);
ashleymills 0:ff9ebe0cf0e9 306 dtls_ec_key_to_uint32(pub_key_y, key_size, pub_y);
ashleymills 0:ff9ebe0cf0e9 307
ashleymills 0:ff9ebe0cf0e9 308 ecc_ecdh(pub_x, pub_y, priv, result_x, result_y);
ashleymills 0:ff9ebe0cf0e9 309
ashleymills 0:ff9ebe0cf0e9 310 dtls_ec_key_from_uint32(result_x, key_size, result);
ashleymills 0:ff9ebe0cf0e9 311 return key_size;
ashleymills 0:ff9ebe0cf0e9 312 }
ashleymills 0:ff9ebe0cf0e9 313
ashleymills 0:ff9ebe0cf0e9 314 void
ashleymills 0:ff9ebe0cf0e9 315 dtls_ecdsa_generate_key(unsigned char *priv_key,
ashleymills 0:ff9ebe0cf0e9 316 unsigned char *pub_key_x,
ashleymills 0:ff9ebe0cf0e9 317 unsigned char *pub_key_y,
ashleymills 0:ff9ebe0cf0e9 318 size_t key_size) {
ashleymills 0:ff9ebe0cf0e9 319 uint32_t priv[8];
ashleymills 0:ff9ebe0cf0e9 320 uint32_t pub_x[8];
ashleymills 0:ff9ebe0cf0e9 321 uint32_t pub_y[8];
ashleymills 0:ff9ebe0cf0e9 322
ashleymills 0:ff9ebe0cf0e9 323 do {
ashleymills 0:ff9ebe0cf0e9 324 prng((unsigned char *)priv, key_size);
ashleymills 0:ff9ebe0cf0e9 325 } while (!ecc_is_valid_key(priv));
ashleymills 0:ff9ebe0cf0e9 326
ashleymills 0:ff9ebe0cf0e9 327 ecc_gen_pub_key(priv, pub_x, pub_y);
ashleymills 0:ff9ebe0cf0e9 328
ashleymills 0:ff9ebe0cf0e9 329 dtls_ec_key_from_uint32(priv, key_size, priv_key);
ashleymills 0:ff9ebe0cf0e9 330 dtls_ec_key_from_uint32(pub_x, key_size, pub_key_x);
ashleymills 0:ff9ebe0cf0e9 331 dtls_ec_key_from_uint32(pub_y, key_size, pub_key_y);
ashleymills 0:ff9ebe0cf0e9 332 }
ashleymills 0:ff9ebe0cf0e9 333
ashleymills 0:ff9ebe0cf0e9 334 /* rfc4492#section-5.4 */
ashleymills 0:ff9ebe0cf0e9 335 void
ashleymills 0:ff9ebe0cf0e9 336 dtls_ecdsa_create_sig_hash(const unsigned char *priv_key, size_t key_size,
ashleymills 0:ff9ebe0cf0e9 337 const unsigned char *sign_hash, size_t sign_hash_size,
ashleymills 0:ff9ebe0cf0e9 338 uint32_t point_r[9], uint32_t point_s[9]) {
ashleymills 0:ff9ebe0cf0e9 339 int ret;
ashleymills 0:ff9ebe0cf0e9 340 uint32_t priv[8];
ashleymills 0:ff9ebe0cf0e9 341 uint32_t hash[8];
ashleymills 0:ff9ebe0cf0e9 342 uint32_t rand[8];
ashleymills 0:ff9ebe0cf0e9 343
ashleymills 0:ff9ebe0cf0e9 344 dtls_ec_key_to_uint32(priv_key, key_size, priv);
ashleymills 0:ff9ebe0cf0e9 345 dtls_ec_key_to_uint32(sign_hash, sign_hash_size, hash);
ashleymills 0:ff9ebe0cf0e9 346 do {
ashleymills 0:ff9ebe0cf0e9 347 prng((unsigned char *)rand, key_size);
ashleymills 0:ff9ebe0cf0e9 348 ret = ecc_ecdsa_sign(priv, hash, rand, point_r, point_s);
ashleymills 0:ff9ebe0cf0e9 349 } while (ret);
ashleymills 0:ff9ebe0cf0e9 350 }
ashleymills 0:ff9ebe0cf0e9 351
ashleymills 0:ff9ebe0cf0e9 352 void
ashleymills 0:ff9ebe0cf0e9 353 dtls_ecdsa_create_sig(const unsigned char *priv_key, size_t key_size,
ashleymills 0:ff9ebe0cf0e9 354 const unsigned char *client_random, size_t client_random_size,
ashleymills 0:ff9ebe0cf0e9 355 const unsigned char *server_random, size_t server_random_size,
ashleymills 0:ff9ebe0cf0e9 356 const unsigned char *keyx_params, size_t keyx_params_size,
ashleymills 0:ff9ebe0cf0e9 357 uint32_t point_r[9], uint32_t point_s[9]) {
ashleymills 0:ff9ebe0cf0e9 358 dtls_hash_ctx data;
ashleymills 0:ff9ebe0cf0e9 359 unsigned char sha256hash[DTLS_HMAC_DIGEST_SIZE];
ashleymills 0:ff9ebe0cf0e9 360
ashleymills 0:ff9ebe0cf0e9 361 dtls_hash_init(&data);
ashleymills 0:ff9ebe0cf0e9 362 dtls_hash_update(&data, client_random, client_random_size);
ashleymills 0:ff9ebe0cf0e9 363 dtls_hash_update(&data, server_random, server_random_size);
ashleymills 0:ff9ebe0cf0e9 364 dtls_hash_update(&data, keyx_params, keyx_params_size);
ashleymills 0:ff9ebe0cf0e9 365 dtls_hash_finalize(sha256hash, &data);
ashleymills 0:ff9ebe0cf0e9 366
ashleymills 0:ff9ebe0cf0e9 367 dtls_ecdsa_create_sig_hash(priv_key, key_size, sha256hash,
ashleymills 0:ff9ebe0cf0e9 368 sizeof(sha256hash), point_r, point_s);
ashleymills 0:ff9ebe0cf0e9 369 }
ashleymills 0:ff9ebe0cf0e9 370
ashleymills 0:ff9ebe0cf0e9 371 /* rfc4492#section-5.4 */
ashleymills 0:ff9ebe0cf0e9 372 int
ashleymills 0:ff9ebe0cf0e9 373 dtls_ecdsa_verify_sig_hash(const unsigned char *pub_key_x,
ashleymills 0:ff9ebe0cf0e9 374 const unsigned char *pub_key_y, size_t key_size,
ashleymills 0:ff9ebe0cf0e9 375 const unsigned char *sign_hash, size_t sign_hash_size,
ashleymills 0:ff9ebe0cf0e9 376 unsigned char *result_r, unsigned char *result_s) {
ashleymills 0:ff9ebe0cf0e9 377 uint32_t pub_x[8];
ashleymills 0:ff9ebe0cf0e9 378 uint32_t pub_y[8];
ashleymills 0:ff9ebe0cf0e9 379 uint32_t hash[8];
ashleymills 0:ff9ebe0cf0e9 380 uint32_t point_r[8];
ashleymills 0:ff9ebe0cf0e9 381 uint32_t point_s[8];
ashleymills 0:ff9ebe0cf0e9 382
ashleymills 0:ff9ebe0cf0e9 383 dtls_ec_key_to_uint32(pub_key_x, key_size, pub_x);
ashleymills 0:ff9ebe0cf0e9 384 dtls_ec_key_to_uint32(pub_key_y, key_size, pub_y);
ashleymills 0:ff9ebe0cf0e9 385 dtls_ec_key_to_uint32(result_r, key_size, point_r);
ashleymills 0:ff9ebe0cf0e9 386 dtls_ec_key_to_uint32(result_s, key_size, point_s);
ashleymills 0:ff9ebe0cf0e9 387 dtls_ec_key_to_uint32(sign_hash, sign_hash_size, hash);
ashleymills 0:ff9ebe0cf0e9 388
ashleymills 0:ff9ebe0cf0e9 389 return ecc_ecdsa_validate(pub_x, pub_y, hash, point_r, point_s);
ashleymills 0:ff9ebe0cf0e9 390 }
ashleymills 0:ff9ebe0cf0e9 391
ashleymills 0:ff9ebe0cf0e9 392 int
ashleymills 0:ff9ebe0cf0e9 393 dtls_ecdsa_verify_sig(const unsigned char *pub_key_x,
ashleymills 0:ff9ebe0cf0e9 394 const unsigned char *pub_key_y, size_t key_size,
ashleymills 0:ff9ebe0cf0e9 395 const unsigned char *client_random, size_t client_random_size,
ashleymills 0:ff9ebe0cf0e9 396 const unsigned char *server_random, size_t server_random_size,
ashleymills 0:ff9ebe0cf0e9 397 const unsigned char *keyx_params, size_t keyx_params_size,
ashleymills 0:ff9ebe0cf0e9 398 unsigned char *result_r, unsigned char *result_s) {
ashleymills 0:ff9ebe0cf0e9 399 dtls_hash_ctx data;
ashleymills 0:ff9ebe0cf0e9 400 unsigned char sha256hash[DTLS_HMAC_DIGEST_SIZE];
ashleymills 0:ff9ebe0cf0e9 401
ashleymills 0:ff9ebe0cf0e9 402 dtls_hash_init(&data);
ashleymills 0:ff9ebe0cf0e9 403 dtls_hash_update(&data, client_random, client_random_size);
ashleymills 0:ff9ebe0cf0e9 404 dtls_hash_update(&data, server_random, server_random_size);
ashleymills 0:ff9ebe0cf0e9 405 dtls_hash_update(&data, keyx_params, keyx_params_size);
ashleymills 0:ff9ebe0cf0e9 406 dtls_hash_finalize(sha256hash, &data);
ashleymills 0:ff9ebe0cf0e9 407
ashleymills 0:ff9ebe0cf0e9 408 return dtls_ecdsa_verify_sig_hash(pub_key_x, pub_key_y, key_size, sha256hash,
ashleymills 0:ff9ebe0cf0e9 409 sizeof(sha256hash), result_r, result_s);
ashleymills 0:ff9ebe0cf0e9 410 }
ashleymills 0:ff9ebe0cf0e9 411
ashleymills 0:ff9ebe0cf0e9 412 dtls_cipher_context_t *
ashleymills 0:ff9ebe0cf0e9 413 dtls_cipher_new(dtls_cipher_t cipher,
ashleymills 0:ff9ebe0cf0e9 414 unsigned char *key, size_t keylen) {
ashleymills 0:ff9ebe0cf0e9 415 dtls_cipher_context_t *cipher_context = NULL;
ashleymills 0:ff9ebe0cf0e9 416
ashleymills 0:ff9ebe0cf0e9 417 cipher_context = dtls_cipher_context_new();
ashleymills 0:ff9ebe0cf0e9 418 if (!cipher_context) {
ashleymills 0:ff9ebe0cf0e9 419 WARN("cannot allocate cipher_context\r\n");
ashleymills 0:ff9ebe0cf0e9 420 return NULL;
ashleymills 0:ff9ebe0cf0e9 421 }
ashleymills 0:ff9ebe0cf0e9 422
ashleymills 0:ff9ebe0cf0e9 423 switch (cipher) {
ashleymills 0:ff9ebe0cf0e9 424 case TLS_PSK_WITH_AES_128_CCM_8:
ashleymills 0:ff9ebe0cf0e9 425 case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: {
ashleymills 0:ff9ebe0cf0e9 426 aes128_ccm_t *ccm_ctx = &cipher_context->data;
ashleymills 0:ff9ebe0cf0e9 427
ashleymills 0:ff9ebe0cf0e9 428 if (rijndael_set_key_enc_only(&ccm_ctx->ctx, key, 8 * keylen) < 0) {
ashleymills 0:ff9ebe0cf0e9 429 /* cleanup everything in case the key has the wrong size */
ashleymills 0:ff9ebe0cf0e9 430 WARN("cannot set rijndael key\n");
ashleymills 0:ff9ebe0cf0e9 431 goto error;
ashleymills 0:ff9ebe0cf0e9 432 }
ashleymills 0:ff9ebe0cf0e9 433 break;
ashleymills 0:ff9ebe0cf0e9 434 }
ashleymills 0:ff9ebe0cf0e9 435 default:
ashleymills 0:ff9ebe0cf0e9 436 WARN("unknown cipher %04x\n", cipher);
ashleymills 0:ff9ebe0cf0e9 437 goto error;
ashleymills 0:ff9ebe0cf0e9 438 }
ashleymills 0:ff9ebe0cf0e9 439
ashleymills 0:ff9ebe0cf0e9 440 return cipher_context;
ashleymills 0:ff9ebe0cf0e9 441 error:
ashleymills 0:ff9ebe0cf0e9 442 dtls_cipher_context_free(cipher_context);
ashleymills 0:ff9ebe0cf0e9 443 return NULL;
ashleymills 0:ff9ebe0cf0e9 444 }
ashleymills 0:ff9ebe0cf0e9 445
ashleymills 0:ff9ebe0cf0e9 446 void
ashleymills 0:ff9ebe0cf0e9 447 dtls_cipher_free(dtls_cipher_context_t *cipher_context) {
ashleymills 0:ff9ebe0cf0e9 448 dtls_cipher_context_free(cipher_context);
ashleymills 0:ff9ebe0cf0e9 449 }
ashleymills 0:ff9ebe0cf0e9 450
ashleymills 0:ff9ebe0cf0e9 451 int
ashleymills 0:ff9ebe0cf0e9 452 dtls_encrypt(dtls_cipher_context_t *ctx,
ashleymills 0:ff9ebe0cf0e9 453 const unsigned char *src, size_t length,
ashleymills 0:ff9ebe0cf0e9 454 unsigned char *buf,
ashleymills 0:ff9ebe0cf0e9 455 unsigned char *nounce,
ashleymills 0:ff9ebe0cf0e9 456 const unsigned char *aad, size_t la) {
ashleymills 0:ff9ebe0cf0e9 457 if (ctx) {
ashleymills 0:ff9ebe0cf0e9 458 if (src != buf)
ashleymills 0:ff9ebe0cf0e9 459 memmove(buf, src, length);
ashleymills 0:ff9ebe0cf0e9 460 return dtls_ccm_encrypt(&ctx->data, src, length, buf, nounce,
ashleymills 0:ff9ebe0cf0e9 461 aad, la);
ashleymills 0:ff9ebe0cf0e9 462 }
ashleymills 0:ff9ebe0cf0e9 463
ashleymills 0:ff9ebe0cf0e9 464 return -1;
ashleymills 0:ff9ebe0cf0e9 465 }
ashleymills 0:ff9ebe0cf0e9 466
ashleymills 0:ff9ebe0cf0e9 467 int
ashleymills 0:ff9ebe0cf0e9 468 dtls_decrypt(dtls_cipher_context_t *ctx,
ashleymills 0:ff9ebe0cf0e9 469 const unsigned char *src, size_t length,
ashleymills 0:ff9ebe0cf0e9 470 unsigned char *buf,
ashleymills 0:ff9ebe0cf0e9 471 unsigned char *nounce,
ashleymills 0:ff9ebe0cf0e9 472 const unsigned char *aad, size_t la) {
ashleymills 0:ff9ebe0cf0e9 473 if (ctx) {
ashleymills 0:ff9ebe0cf0e9 474 if (src != buf)
ashleymills 0:ff9ebe0cf0e9 475 memmove(buf, src, length);
ashleymills 0:ff9ebe0cf0e9 476 return dtls_ccm_decrypt(&ctx->data, src, length, buf, nounce,
ashleymills 0:ff9ebe0cf0e9 477 aad, la);
ashleymills 0:ff9ebe0cf0e9 478 }
ashleymills 0:ff9ebe0cf0e9 479
ashleymills 0:ff9ebe0cf0e9 480 return -1;
ashleymills 0:ff9ebe0cf0e9 481 }
ashleymills 0:ff9ebe0cf0e9 482