Version 0.5.0 of tinydtls

Dependents:   tinydtls_test_cellular tinydtls_test_ethernet tiny-dtls

Committer:
ashleymills
Date:
Fri Oct 18 13:18:30 2013 +0000
Revision:
0:ff9ebe0cf0e9
Upgraded to tinydtls 0.5.0

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 *
ashleymills 0:ff9ebe0cf0e9 5 * Permission is hereby granted, free of charge, to any person
ashleymills 0:ff9ebe0cf0e9 6 * obtaining a copy of this software and associated documentation
ashleymills 0:ff9ebe0cf0e9 7 * files (the "Software"), to deal in the Software without
ashleymills 0:ff9ebe0cf0e9 8 * restriction, including without limitation the rights to use, copy,
ashleymills 0:ff9ebe0cf0e9 9 * modify, merge, publish, distribute, sublicense, and/or sell copies
ashleymills 0:ff9ebe0cf0e9 10 * of the Software, and to permit persons to whom the Software is
ashleymills 0:ff9ebe0cf0e9 11 * furnished to do so, subject to the following conditions:
ashleymills 0:ff9ebe0cf0e9 12 *
ashleymills 0:ff9ebe0cf0e9 13 * The above copyright notice and this permission notice shall be
ashleymills 0:ff9ebe0cf0e9 14 * included in all copies or substantial portions of the Software.
ashleymills 0:ff9ebe0cf0e9 15 *
ashleymills 0:ff9ebe0cf0e9 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
ashleymills 0:ff9ebe0cf0e9 17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
ashleymills 0:ff9ebe0cf0e9 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
ashleymills 0:ff9ebe0cf0e9 19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
ashleymills 0:ff9ebe0cf0e9 20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ashleymills 0:ff9ebe0cf0e9 21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
ashleymills 0:ff9ebe0cf0e9 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
ashleymills 0:ff9ebe0cf0e9 23 * SOFTWARE.
ashleymills 0:ff9ebe0cf0e9 24 */
ashleymills 0:ff9ebe0cf0e9 25
ashleymills 0:ff9ebe0cf0e9 26 #include <string.h>
ashleymills 0:ff9ebe0cf0e9 27
ashleymills 0:ff9ebe0cf0e9 28 #include "global.h"
ashleymills 0:ff9ebe0cf0e9 29 #include "numeric.h"
ashleymills 0:ff9ebe0cf0e9 30 #include "ccm.h"
ashleymills 0:ff9ebe0cf0e9 31
ashleymills 0:ff9ebe0cf0e9 32 #define CCM_FLAGS(A,M,L) (((A > 0) << 6) | (((M - 2)/2) << 3) | (L - 1))
ashleymills 0:ff9ebe0cf0e9 33
ashleymills 0:ff9ebe0cf0e9 34 #define MASK_L(_L) ((1 << 8 * _L) - 1)
ashleymills 0:ff9ebe0cf0e9 35
ashleymills 0:ff9ebe0cf0e9 36 #define SET_COUNTER(A,L,cnt,C) { \
ashleymills 0:ff9ebe0cf0e9 37 int i; \
ashleymills 0:ff9ebe0cf0e9 38 memset((A) + DTLS_CCM_BLOCKSIZE - (L), 0, (L)); \
ashleymills 0:ff9ebe0cf0e9 39 (C) = (cnt) & MASK_L(L); \
ashleymills 0:ff9ebe0cf0e9 40 for (i = DTLS_CCM_BLOCKSIZE - 1; (C) && (i > (L)); --i, (C) >>= 8) \
ashleymills 0:ff9ebe0cf0e9 41 (A)[i] |= (C) & 0xFF; \
ashleymills 0:ff9ebe0cf0e9 42 }
ashleymills 0:ff9ebe0cf0e9 43
ashleymills 0:ff9ebe0cf0e9 44 static inline void
ashleymills 0:ff9ebe0cf0e9 45 block0(size_t M, /* number of auth bytes */
ashleymills 0:ff9ebe0cf0e9 46 size_t L, /* number of bytes to encode message length */
ashleymills 0:ff9ebe0cf0e9 47 size_t la, /* l(a) octets additional authenticated data */
ashleymills 0:ff9ebe0cf0e9 48 size_t lm, /* l(m) message length */
ashleymills 0:ff9ebe0cf0e9 49 unsigned char nonce[DTLS_CCM_BLOCKSIZE],
ashleymills 0:ff9ebe0cf0e9 50 unsigned char *result) {
ashleymills 0:ff9ebe0cf0e9 51 int i;
ashleymills 0:ff9ebe0cf0e9 52
ashleymills 0:ff9ebe0cf0e9 53 result[0] = CCM_FLAGS(la, M, L);
ashleymills 0:ff9ebe0cf0e9 54
ashleymills 0:ff9ebe0cf0e9 55 /* copy the nonce */
ashleymills 0:ff9ebe0cf0e9 56 memcpy(result + 1, nonce, DTLS_CCM_BLOCKSIZE - L);
ashleymills 0:ff9ebe0cf0e9 57
ashleymills 0:ff9ebe0cf0e9 58 for (i=0; i < L; i++) {
ashleymills 0:ff9ebe0cf0e9 59 result[15-i] = lm & 0xff;
ashleymills 0:ff9ebe0cf0e9 60 lm >>= 8;
ashleymills 0:ff9ebe0cf0e9 61 }
ashleymills 0:ff9ebe0cf0e9 62 }
ashleymills 0:ff9ebe0cf0e9 63
ashleymills 0:ff9ebe0cf0e9 64 /**
ashleymills 0:ff9ebe0cf0e9 65 * Creates the CBC-MAC for the additional authentication data that
ashleymills 0:ff9ebe0cf0e9 66 * is sent in cleartext.
ashleymills 0:ff9ebe0cf0e9 67 *
ashleymills 0:ff9ebe0cf0e9 68 * \param ctx The crypto context for the AES encryption.
ashleymills 0:ff9ebe0cf0e9 69 * \param msg The message starting with the additional authentication data.
ashleymills 0:ff9ebe0cf0e9 70 * \param la The number of additional authentication bytes in \p msg.
ashleymills 0:ff9ebe0cf0e9 71 * \param B The input buffer for crypto operations. When this function
ashleymills 0:ff9ebe0cf0e9 72 * is called, \p B must be initialized with \c B0 (the first
ashleymills 0:ff9ebe0cf0e9 73 * authentication block.
ashleymills 0:ff9ebe0cf0e9 74 * \param X The output buffer where the result of the CBC calculation
ashleymills 0:ff9ebe0cf0e9 75 * is placed.
ashleymills 0:ff9ebe0cf0e9 76 * \return The result is written to \p X.
ashleymills 0:ff9ebe0cf0e9 77 */
ashleymills 0:ff9ebe0cf0e9 78 static void
ashleymills 0:ff9ebe0cf0e9 79 add_auth_data(rijndael_ctx *ctx, const unsigned char *msg, size_t la,
ashleymills 0:ff9ebe0cf0e9 80 unsigned char B[DTLS_CCM_BLOCKSIZE],
ashleymills 0:ff9ebe0cf0e9 81 unsigned char X[DTLS_CCM_BLOCKSIZE]) {
ashleymills 0:ff9ebe0cf0e9 82 size_t i,j;
ashleymills 0:ff9ebe0cf0e9 83
ashleymills 0:ff9ebe0cf0e9 84 rijndael_encrypt(ctx, B, X);
ashleymills 0:ff9ebe0cf0e9 85
ashleymills 0:ff9ebe0cf0e9 86 memset(B, 0, DTLS_CCM_BLOCKSIZE);
ashleymills 0:ff9ebe0cf0e9 87
ashleymills 0:ff9ebe0cf0e9 88 if (!la)
ashleymills 0:ff9ebe0cf0e9 89 return;
ashleymills 0:ff9ebe0cf0e9 90
ashleymills 0:ff9ebe0cf0e9 91 #ifndef WITH_CONTIKI
ashleymills 0:ff9ebe0cf0e9 92 if (la < 0xFF00) { /* 2^16 - 2^8 */
ashleymills 0:ff9ebe0cf0e9 93 j = 2;
ashleymills 0:ff9ebe0cf0e9 94 dtls_int_to_uint16(B, la);
ashleymills 0:ff9ebe0cf0e9 95 } else if (la <= UINT32_MAX) {
ashleymills 0:ff9ebe0cf0e9 96 j = 6;
ashleymills 0:ff9ebe0cf0e9 97 dtls_int_to_uint16(B, 0xFFFE);
ashleymills 0:ff9ebe0cf0e9 98 dtls_int_to_uint32(B+2, la);
ashleymills 0:ff9ebe0cf0e9 99 } else {
ashleymills 0:ff9ebe0cf0e9 100 j = 10;
ashleymills 0:ff9ebe0cf0e9 101 dtls_int_to_uint16(B, 0xFFFF);
ashleymills 0:ff9ebe0cf0e9 102 dtls_ulong_to_uint64(B+2, la);
ashleymills 0:ff9ebe0cf0e9 103 }
ashleymills 0:ff9ebe0cf0e9 104 #else /* WITH_CONTIKI */
ashleymills 0:ff9ebe0cf0e9 105 /* With Contiki, we are building for small devices and thus
ashleymills 0:ff9ebe0cf0e9 106 * anticipate that the number of additional authentication bytes
ashleymills 0:ff9ebe0cf0e9 107 * will not exceed 65280 bytes (0xFF00) and we can skip the
ashleymills 0:ff9ebe0cf0e9 108 * workarounds required for j=6 and j=10 on devices with a word size
ashleymills 0:ff9ebe0cf0e9 109 * of 32 bits or 64 bits, respectively.
ashleymills 0:ff9ebe0cf0e9 110 */
ashleymills 0:ff9ebe0cf0e9 111
ashleymills 0:ff9ebe0cf0e9 112 assert(la < 0xFF00);
ashleymills 0:ff9ebe0cf0e9 113 j = 2;
ashleymills 0:ff9ebe0cf0e9 114 dtls_int_to_uint16(B, la);
ashleymills 0:ff9ebe0cf0e9 115 #endif /* WITH_CONTIKI */
ashleymills 0:ff9ebe0cf0e9 116
ashleymills 0:ff9ebe0cf0e9 117 i = min(DTLS_CCM_BLOCKSIZE - j, la);
ashleymills 0:ff9ebe0cf0e9 118 memcpy(B + j, msg, i);
ashleymills 0:ff9ebe0cf0e9 119 la -= i;
ashleymills 0:ff9ebe0cf0e9 120 msg += i;
ashleymills 0:ff9ebe0cf0e9 121
ashleymills 0:ff9ebe0cf0e9 122 memxor(B, X, DTLS_CCM_BLOCKSIZE);
ashleymills 0:ff9ebe0cf0e9 123
ashleymills 0:ff9ebe0cf0e9 124 rijndael_encrypt(ctx, B, X);
ashleymills 0:ff9ebe0cf0e9 125
ashleymills 0:ff9ebe0cf0e9 126 while (la > DTLS_CCM_BLOCKSIZE) {
ashleymills 0:ff9ebe0cf0e9 127 for (i = 0; i < DTLS_CCM_BLOCKSIZE; ++i)
ashleymills 0:ff9ebe0cf0e9 128 B[i] = X[i] ^ *msg++;
ashleymills 0:ff9ebe0cf0e9 129 la -= DTLS_CCM_BLOCKSIZE;
ashleymills 0:ff9ebe0cf0e9 130
ashleymills 0:ff9ebe0cf0e9 131 rijndael_encrypt(ctx, B, X);
ashleymills 0:ff9ebe0cf0e9 132 }
ashleymills 0:ff9ebe0cf0e9 133
ashleymills 0:ff9ebe0cf0e9 134 if (la) {
ashleymills 0:ff9ebe0cf0e9 135 memset(B, 0, DTLS_CCM_BLOCKSIZE);
ashleymills 0:ff9ebe0cf0e9 136 memcpy(B, msg, la);
ashleymills 0:ff9ebe0cf0e9 137 memxor(B, X, DTLS_CCM_BLOCKSIZE);
ashleymills 0:ff9ebe0cf0e9 138
ashleymills 0:ff9ebe0cf0e9 139 rijndael_encrypt(ctx, B, X);
ashleymills 0:ff9ebe0cf0e9 140 }
ashleymills 0:ff9ebe0cf0e9 141 }
ashleymills 0:ff9ebe0cf0e9 142
ashleymills 0:ff9ebe0cf0e9 143 static inline void
ashleymills 0:ff9ebe0cf0e9 144 encrypt(rijndael_ctx *ctx, size_t L, unsigned long counter,
ashleymills 0:ff9ebe0cf0e9 145 unsigned char *msg, size_t len,
ashleymills 0:ff9ebe0cf0e9 146 unsigned char A[DTLS_CCM_BLOCKSIZE],
ashleymills 0:ff9ebe0cf0e9 147 unsigned char S[DTLS_CCM_BLOCKSIZE]) {
ashleymills 0:ff9ebe0cf0e9 148
ashleymills 0:ff9ebe0cf0e9 149 static unsigned long counter_tmp;
ashleymills 0:ff9ebe0cf0e9 150
ashleymills 0:ff9ebe0cf0e9 151 SET_COUNTER(A, L, counter, counter_tmp);
ashleymills 0:ff9ebe0cf0e9 152 rijndael_encrypt(ctx, A, S);
ashleymills 0:ff9ebe0cf0e9 153 memxor(msg, S, len);
ashleymills 0:ff9ebe0cf0e9 154 }
ashleymills 0:ff9ebe0cf0e9 155
ashleymills 0:ff9ebe0cf0e9 156 static inline void
ashleymills 0:ff9ebe0cf0e9 157 mac(rijndael_ctx *ctx,
ashleymills 0:ff9ebe0cf0e9 158 unsigned char *msg, size_t len,
ashleymills 0:ff9ebe0cf0e9 159 unsigned char B[DTLS_CCM_BLOCKSIZE],
ashleymills 0:ff9ebe0cf0e9 160 unsigned char X[DTLS_CCM_BLOCKSIZE]) {
ashleymills 0:ff9ebe0cf0e9 161 size_t i;
ashleymills 0:ff9ebe0cf0e9 162
ashleymills 0:ff9ebe0cf0e9 163 for (i = 0; i < len; ++i)
ashleymills 0:ff9ebe0cf0e9 164 B[i] = X[i] ^ msg[i];
ashleymills 0:ff9ebe0cf0e9 165
ashleymills 0:ff9ebe0cf0e9 166 rijndael_encrypt(ctx, B, X);
ashleymills 0:ff9ebe0cf0e9 167
ashleymills 0:ff9ebe0cf0e9 168 }
ashleymills 0:ff9ebe0cf0e9 169
ashleymills 0:ff9ebe0cf0e9 170 long int
ashleymills 0:ff9ebe0cf0e9 171 dtls_ccm_encrypt_message(rijndael_ctx *ctx, size_t M, size_t L,
ashleymills 0:ff9ebe0cf0e9 172 unsigned char nonce[DTLS_CCM_BLOCKSIZE],
ashleymills 0:ff9ebe0cf0e9 173 unsigned char *msg, size_t lm,
ashleymills 0:ff9ebe0cf0e9 174 const unsigned char *aad, size_t la) {
ashleymills 0:ff9ebe0cf0e9 175 size_t i, len;
ashleymills 0:ff9ebe0cf0e9 176 unsigned long counter_tmp;
ashleymills 0:ff9ebe0cf0e9 177 unsigned long counter = 1; /* \bug does not work correctly on ia32 when
ashleymills 0:ff9ebe0cf0e9 178 lm >= 2^16 */
ashleymills 0:ff9ebe0cf0e9 179 unsigned char A[DTLS_CCM_BLOCKSIZE]; /* A_i blocks for encryption input */
ashleymills 0:ff9ebe0cf0e9 180 unsigned char B[DTLS_CCM_BLOCKSIZE]; /* B_i blocks for CBC-MAC input */
ashleymills 0:ff9ebe0cf0e9 181 unsigned char S[DTLS_CCM_BLOCKSIZE]; /* S_i = encrypted A_i blocks */
ashleymills 0:ff9ebe0cf0e9 182 unsigned char X[DTLS_CCM_BLOCKSIZE]; /* X_i = encrypted B_i blocks */
ashleymills 0:ff9ebe0cf0e9 183
ashleymills 0:ff9ebe0cf0e9 184 len = lm; /* save original length */
ashleymills 0:ff9ebe0cf0e9 185 /* create the initial authentication block B0 */
ashleymills 0:ff9ebe0cf0e9 186 block0(M, L, la, lm, nonce, B);
ashleymills 0:ff9ebe0cf0e9 187 add_auth_data(ctx, aad, la, B, X);
ashleymills 0:ff9ebe0cf0e9 188
ashleymills 0:ff9ebe0cf0e9 189 /* initialize block template */
ashleymills 0:ff9ebe0cf0e9 190 A[0] = L-1;
ashleymills 0:ff9ebe0cf0e9 191
ashleymills 0:ff9ebe0cf0e9 192 /* copy the nonce */
ashleymills 0:ff9ebe0cf0e9 193 memcpy(A + 1, nonce, DTLS_CCM_BLOCKSIZE - L);
ashleymills 0:ff9ebe0cf0e9 194
ashleymills 0:ff9ebe0cf0e9 195 while (lm >= DTLS_CCM_BLOCKSIZE) {
ashleymills 0:ff9ebe0cf0e9 196 /* calculate MAC */
ashleymills 0:ff9ebe0cf0e9 197 mac(ctx, msg, DTLS_CCM_BLOCKSIZE, B, X);
ashleymills 0:ff9ebe0cf0e9 198
ashleymills 0:ff9ebe0cf0e9 199 /* encrypt */
ashleymills 0:ff9ebe0cf0e9 200 encrypt(ctx, L, counter, msg, DTLS_CCM_BLOCKSIZE, A, S);
ashleymills 0:ff9ebe0cf0e9 201
ashleymills 0:ff9ebe0cf0e9 202 /* update local pointers */
ashleymills 0:ff9ebe0cf0e9 203 lm -= DTLS_CCM_BLOCKSIZE;
ashleymills 0:ff9ebe0cf0e9 204 msg += DTLS_CCM_BLOCKSIZE;
ashleymills 0:ff9ebe0cf0e9 205 counter++;
ashleymills 0:ff9ebe0cf0e9 206 }
ashleymills 0:ff9ebe0cf0e9 207
ashleymills 0:ff9ebe0cf0e9 208 if (lm) {
ashleymills 0:ff9ebe0cf0e9 209 /* Calculate MAC. The remainder of B must be padded with zeroes, so
ashleymills 0:ff9ebe0cf0e9 210 * B is constructed to contain X ^ msg for the first lm bytes (done in
ashleymills 0:ff9ebe0cf0e9 211 * mac() and X ^ 0 for the remaining DTLS_CCM_BLOCKSIZE - lm bytes
ashleymills 0:ff9ebe0cf0e9 212 * (i.e., we can use memcpy() here).
ashleymills 0:ff9ebe0cf0e9 213 */
ashleymills 0:ff9ebe0cf0e9 214 memcpy(B + lm, X + lm, DTLS_CCM_BLOCKSIZE - lm);
ashleymills 0:ff9ebe0cf0e9 215 mac(ctx, msg, lm, B, X);
ashleymills 0:ff9ebe0cf0e9 216
ashleymills 0:ff9ebe0cf0e9 217 /* encrypt */
ashleymills 0:ff9ebe0cf0e9 218 encrypt(ctx, L, counter, msg, lm, A, S);
ashleymills 0:ff9ebe0cf0e9 219
ashleymills 0:ff9ebe0cf0e9 220 /* update local pointers */
ashleymills 0:ff9ebe0cf0e9 221 msg += lm;
ashleymills 0:ff9ebe0cf0e9 222 }
ashleymills 0:ff9ebe0cf0e9 223
ashleymills 0:ff9ebe0cf0e9 224 /* calculate S_0 */
ashleymills 0:ff9ebe0cf0e9 225 SET_COUNTER(A, L, 0, counter_tmp);
ashleymills 0:ff9ebe0cf0e9 226 rijndael_encrypt(ctx, A, S);
ashleymills 0:ff9ebe0cf0e9 227
ashleymills 0:ff9ebe0cf0e9 228 for (i = 0; i < M; ++i)
ashleymills 0:ff9ebe0cf0e9 229 *msg++ = X[i] ^ S[i];
ashleymills 0:ff9ebe0cf0e9 230
ashleymills 0:ff9ebe0cf0e9 231 return len + M;
ashleymills 0:ff9ebe0cf0e9 232 }
ashleymills 0:ff9ebe0cf0e9 233
ashleymills 0:ff9ebe0cf0e9 234 long int
ashleymills 0:ff9ebe0cf0e9 235 dtls_ccm_decrypt_message(rijndael_ctx *ctx, size_t M, size_t L,
ashleymills 0:ff9ebe0cf0e9 236 unsigned char nonce[DTLS_CCM_BLOCKSIZE],
ashleymills 0:ff9ebe0cf0e9 237 unsigned char *msg, size_t lm,
ashleymills 0:ff9ebe0cf0e9 238 const unsigned char *aad, size_t la) {
ashleymills 0:ff9ebe0cf0e9 239
ashleymills 0:ff9ebe0cf0e9 240 size_t len;
ashleymills 0:ff9ebe0cf0e9 241 unsigned long counter_tmp;
ashleymills 0:ff9ebe0cf0e9 242 unsigned long counter = 1; /* \bug does not work correctly on ia32 when
ashleymills 0:ff9ebe0cf0e9 243 lm >= 2^16 */
ashleymills 0:ff9ebe0cf0e9 244 unsigned char A[DTLS_CCM_BLOCKSIZE]; /* A_i blocks for encryption input */
ashleymills 0:ff9ebe0cf0e9 245 unsigned char B[DTLS_CCM_BLOCKSIZE]; /* B_i blocks for CBC-MAC input */
ashleymills 0:ff9ebe0cf0e9 246 unsigned char S[DTLS_CCM_BLOCKSIZE]; /* S_i = encrypted A_i blocks */
ashleymills 0:ff9ebe0cf0e9 247 unsigned char X[DTLS_CCM_BLOCKSIZE]; /* X_i = encrypted B_i blocks */
ashleymills 0:ff9ebe0cf0e9 248
ashleymills 0:ff9ebe0cf0e9 249 if (lm < M)
ashleymills 0:ff9ebe0cf0e9 250 goto error;
ashleymills 0:ff9ebe0cf0e9 251
ashleymills 0:ff9ebe0cf0e9 252 len = lm; /* save original length */
ashleymills 0:ff9ebe0cf0e9 253 lm -= M; /* detract MAC size*/
ashleymills 0:ff9ebe0cf0e9 254
ashleymills 0:ff9ebe0cf0e9 255 /* create the initial authentication block B0 */
ashleymills 0:ff9ebe0cf0e9 256 block0(M, L, la, lm, nonce, B);
ashleymills 0:ff9ebe0cf0e9 257 add_auth_data(ctx, aad, la, B, X);
ashleymills 0:ff9ebe0cf0e9 258
ashleymills 0:ff9ebe0cf0e9 259 /* initialize block template */
ashleymills 0:ff9ebe0cf0e9 260 A[0] = L-1;
ashleymills 0:ff9ebe0cf0e9 261
ashleymills 0:ff9ebe0cf0e9 262 /* copy the nonce */
ashleymills 0:ff9ebe0cf0e9 263 memcpy(A + 1, nonce, DTLS_CCM_BLOCKSIZE - L);
ashleymills 0:ff9ebe0cf0e9 264
ashleymills 0:ff9ebe0cf0e9 265 while (lm >= DTLS_CCM_BLOCKSIZE) {
ashleymills 0:ff9ebe0cf0e9 266 /* decrypt */
ashleymills 0:ff9ebe0cf0e9 267 encrypt(ctx, L, counter, msg, DTLS_CCM_BLOCKSIZE, A, S);
ashleymills 0:ff9ebe0cf0e9 268
ashleymills 0:ff9ebe0cf0e9 269 /* calculate MAC */
ashleymills 0:ff9ebe0cf0e9 270 mac(ctx, msg, DTLS_CCM_BLOCKSIZE, B, X);
ashleymills 0:ff9ebe0cf0e9 271
ashleymills 0:ff9ebe0cf0e9 272 /* update local pointers */
ashleymills 0:ff9ebe0cf0e9 273 lm -= DTLS_CCM_BLOCKSIZE;
ashleymills 0:ff9ebe0cf0e9 274 msg += DTLS_CCM_BLOCKSIZE;
ashleymills 0:ff9ebe0cf0e9 275 counter++;
ashleymills 0:ff9ebe0cf0e9 276 }
ashleymills 0:ff9ebe0cf0e9 277
ashleymills 0:ff9ebe0cf0e9 278 if (lm) {
ashleymills 0:ff9ebe0cf0e9 279 /* decrypt */
ashleymills 0:ff9ebe0cf0e9 280 encrypt(ctx, L, counter, msg, lm, A, S);
ashleymills 0:ff9ebe0cf0e9 281
ashleymills 0:ff9ebe0cf0e9 282 /* Calculate MAC. Note that msg ends in the MAC so we must
ashleymills 0:ff9ebe0cf0e9 283 * construct B to contain X ^ msg for the first lm bytes (done in
ashleymills 0:ff9ebe0cf0e9 284 * mac() and X ^ 0 for the remaining DTLS_CCM_BLOCKSIZE - lm bytes
ashleymills 0:ff9ebe0cf0e9 285 * (i.e., we can use memcpy() here).
ashleymills 0:ff9ebe0cf0e9 286 */
ashleymills 0:ff9ebe0cf0e9 287 memcpy(B + lm, X + lm, DTLS_CCM_BLOCKSIZE - lm);
ashleymills 0:ff9ebe0cf0e9 288 mac(ctx, msg, lm, B, X);
ashleymills 0:ff9ebe0cf0e9 289
ashleymills 0:ff9ebe0cf0e9 290 /* update local pointers */
ashleymills 0:ff9ebe0cf0e9 291 msg += lm;
ashleymills 0:ff9ebe0cf0e9 292 }
ashleymills 0:ff9ebe0cf0e9 293
ashleymills 0:ff9ebe0cf0e9 294 /* calculate S_0 */
ashleymills 0:ff9ebe0cf0e9 295 SET_COUNTER(A, L, 0, counter_tmp);
ashleymills 0:ff9ebe0cf0e9 296 rijndael_encrypt(ctx, A, S);
ashleymills 0:ff9ebe0cf0e9 297
ashleymills 0:ff9ebe0cf0e9 298 memxor(msg, S, M);
ashleymills 0:ff9ebe0cf0e9 299
ashleymills 0:ff9ebe0cf0e9 300 /* return length if MAC is valid, otherwise continue with error handling */
ashleymills 0:ff9ebe0cf0e9 301 if (memcmp(X, msg, M) == 0)
ashleymills 0:ff9ebe0cf0e9 302 return len - M;
ashleymills 0:ff9ebe0cf0e9 303
ashleymills 0:ff9ebe0cf0e9 304 error:
ashleymills 0:ff9ebe0cf0e9 305 return -1;
ashleymills 0:ff9ebe0cf0e9 306 }