Ashley Mills / Mbed 2 deprecated tinydtls_test_cellular

Dependencies:   VodafoneUSBModem mbed-rtos mbed tinydtls

Committer:
ashleymills
Date:
Wed Oct 09 14:48:52 2013 +0000
Revision:
0:6ae42a2aff75
Test program for mbed port of tinydtls

Who changed what in which revision?

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