1 /* dtls -- a very basic DTLS implementation
3 * Copyright (C) 2011--2014 Olaf Bergmann <bergmann@tzi.org>
5 * Permission is hereby granted, free of charge, to any person
6 * obtaining a copy of this software and associated documentation
7 * files (the "Software"), to deal in the Software without
8 * restriction, including without limitation the rights to use, copy,
9 * modify, merge, publish, distribute, sublicense, and/or sell copies
10 * of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 #include "dtls_config.h"
37 #define CCM_FLAGS(A,M,L) (((A > 0) << 6) | (((M - 2)/2) << 3) | (L - 1))
39 #define MASK_L(_L) ((1 << 8 * _L) - 1)
41 #define SET_COUNTER(A,L,cnt,C) { \
43 memset((A) + DTLS_CCM_BLOCKSIZE - (L), 0, (L)); \
44 (C) = (cnt) & MASK_L(L); \
45 for (i = DTLS_CCM_BLOCKSIZE - 1; (C) && (i > (L)); --i, (C) >>= 8) \
46 (A)[i] |= (C) & 0xFF; \
50 block0(size_t M, /* number of auth bytes */
51 size_t L, /* number of bytes to encode message length */
52 size_t la, /* l(a) octets additional authenticated data */
53 size_t lm, /* l(m) message length */
54 unsigned char nonce[DTLS_CCM_BLOCKSIZE],
55 unsigned char *result) {
58 result[0] = CCM_FLAGS(la, M, L);
61 memcpy(result + 1, nonce, DTLS_CCM_BLOCKSIZE - L);
63 for (i=0; i < L; i++) {
64 result[15-i] = lm & 0xff;
70 * Creates the CBC-MAC for the additional authentication data that
71 * is sent in cleartext.
73 * \param ctx The crypto context for the AES encryption.
74 * \param msg The message starting with the additional authentication data.
75 * \param la The number of additional authentication bytes in \p msg.
76 * \param B The input buffer for crypto operations. When this function
77 * is called, \p B must be initialized with \c B0 (the first
78 * authentication block.
79 * \param X The output buffer where the result of the CBC calculation
81 * \return The result is written to \p X.
84 add_auth_data(rijndael_ctx *ctx, const unsigned char *msg, size_t la,
85 unsigned char B[DTLS_CCM_BLOCKSIZE],
86 unsigned char X[DTLS_CCM_BLOCKSIZE]) {
89 rijndael_encrypt(ctx, B, X);
91 memset(B, 0, DTLS_CCM_BLOCKSIZE);
97 if (la < 0xFF00) { /* 2^16 - 2^8 */
99 dtls_int_to_uint16(B, la);
100 } else if (la <= UINT32_MAX) {
102 dtls_int_to_uint16(B, 0xFFFE);
103 dtls_int_to_uint32(B+2, la);
106 dtls_int_to_uint16(B, 0xFFFF);
107 dtls_int_to_uint64(B+2, la);
109 #else /* WITH_CONTIKI */
110 /* With Contiki, we are building for small devices and thus
111 * anticipate that the number of additional authentication bytes
112 * will not exceed 65280 bytes (0xFF00) and we can skip the
113 * workarounds required for j=6 and j=10 on devices with a word size
114 * of 32 bits or 64 bits, respectively.
119 dtls_int_to_uint16(B, la);
120 #endif /* WITH_CONTIKI */
122 i = min(DTLS_CCM_BLOCKSIZE - j, la);
123 memcpy(B + j, msg, i);
127 memxor(B, X, DTLS_CCM_BLOCKSIZE);
129 rijndael_encrypt(ctx, B, X);
131 while (la > DTLS_CCM_BLOCKSIZE) {
132 for (i = 0; i < DTLS_CCM_BLOCKSIZE; ++i)
133 B[i] = X[i] ^ *msg++;
134 la -= DTLS_CCM_BLOCKSIZE;
136 rijndael_encrypt(ctx, B, X);
140 memset(B, 0, DTLS_CCM_BLOCKSIZE);
142 memxor(B, X, DTLS_CCM_BLOCKSIZE);
144 rijndael_encrypt(ctx, B, X);
149 encrypt(rijndael_ctx *ctx, size_t L, unsigned long counter,
150 unsigned char *msg, size_t len,
151 unsigned char A[DTLS_CCM_BLOCKSIZE],
152 unsigned char S[DTLS_CCM_BLOCKSIZE]) {
154 static unsigned long counter_tmp;
156 SET_COUNTER(A, L, counter, counter_tmp);
157 rijndael_encrypt(ctx, A, S);
162 mac(rijndael_ctx *ctx,
163 unsigned char *msg, size_t len,
164 unsigned char B[DTLS_CCM_BLOCKSIZE],
165 unsigned char X[DTLS_CCM_BLOCKSIZE]) {
168 for (i = 0; i < len; ++i)
169 B[i] = X[i] ^ msg[i];
171 rijndael_encrypt(ctx, B, X);
176 dtls_ccm_encrypt_message(rijndael_ctx *ctx, size_t M, size_t L,
177 unsigned char nonce[DTLS_CCM_BLOCKSIZE],
178 unsigned char *msg, size_t lm,
179 const unsigned char *aad, size_t la) {
181 unsigned long counter_tmp;
182 unsigned long counter = 1; /* \bug does not work correctly on ia32 when
184 unsigned char A[DTLS_CCM_BLOCKSIZE]; /* A_i blocks for encryption input */
185 unsigned char B[DTLS_CCM_BLOCKSIZE]; /* B_i blocks for CBC-MAC input */
186 unsigned char S[DTLS_CCM_BLOCKSIZE]; /* S_i = encrypted A_i blocks */
187 unsigned char X[DTLS_CCM_BLOCKSIZE]; /* X_i = encrypted B_i blocks */
189 len = lm; /* save original length */
190 /* create the initial authentication block B0 */
191 block0(M, L, la, lm, nonce, B);
192 add_auth_data(ctx, aad, la, B, X);
194 /* initialize block template */
198 memcpy(A + 1, nonce, DTLS_CCM_BLOCKSIZE - L);
200 while (lm >= DTLS_CCM_BLOCKSIZE) {
202 mac(ctx, msg, DTLS_CCM_BLOCKSIZE, B, X);
205 encrypt(ctx, L, counter, msg, DTLS_CCM_BLOCKSIZE, A, S);
207 /* update local pointers */
208 lm -= DTLS_CCM_BLOCKSIZE;
209 msg += DTLS_CCM_BLOCKSIZE;
214 /* Calculate MAC. The remainder of B must be padded with zeroes, so
215 * B is constructed to contain X ^ msg for the first lm bytes (done in
216 * mac() and X ^ 0 for the remaining DTLS_CCM_BLOCKSIZE - lm bytes
217 * (i.e., we can use memcpy() here).
219 memcpy(B + lm, X + lm, DTLS_CCM_BLOCKSIZE - lm);
220 mac(ctx, msg, lm, B, X);
223 encrypt(ctx, L, counter, msg, lm, A, S);
225 /* update local pointers */
230 SET_COUNTER(A, L, 0, counter_tmp);
231 rijndael_encrypt(ctx, A, S);
233 for (i = 0; i < M; ++i)
234 *msg++ = X[i] ^ S[i];
240 dtls_ccm_decrypt_message(rijndael_ctx *ctx, size_t M, size_t L,
241 unsigned char nonce[DTLS_CCM_BLOCKSIZE],
242 unsigned char *msg, size_t lm,
243 const unsigned char *aad, size_t la) {
246 unsigned long counter_tmp;
247 unsigned long counter = 1; /* \bug does not work correctly on ia32 when
249 unsigned char A[DTLS_CCM_BLOCKSIZE]; /* A_i blocks for encryption input */
250 unsigned char B[DTLS_CCM_BLOCKSIZE]; /* B_i blocks for CBC-MAC input */
251 unsigned char S[DTLS_CCM_BLOCKSIZE]; /* S_i = encrypted A_i blocks */
252 unsigned char X[DTLS_CCM_BLOCKSIZE]; /* X_i = encrypted B_i blocks */
257 len = lm; /* save original length */
258 lm -= M; /* detract MAC size*/
260 /* create the initial authentication block B0 */
261 block0(M, L, la, lm, nonce, B);
262 add_auth_data(ctx, aad, la, B, X);
264 /* initialize block template */
268 memcpy(A + 1, nonce, DTLS_CCM_BLOCKSIZE - L);
270 while (lm >= DTLS_CCM_BLOCKSIZE) {
272 encrypt(ctx, L, counter, msg, DTLS_CCM_BLOCKSIZE, A, S);
275 mac(ctx, msg, DTLS_CCM_BLOCKSIZE, B, X);
277 /* update local pointers */
278 lm -= DTLS_CCM_BLOCKSIZE;
279 msg += DTLS_CCM_BLOCKSIZE;
285 encrypt(ctx, L, counter, msg, lm, A, S);
287 /* Calculate MAC. Note that msg ends in the MAC so we must
288 * construct B to contain X ^ msg for the first lm bytes (done in
289 * mac() and X ^ 0 for the remaining DTLS_CCM_BLOCKSIZE - lm bytes
290 * (i.e., we can use memcpy() here).
292 memcpy(B + lm, X + lm, DTLS_CCM_BLOCKSIZE - lm);
293 mac(ctx, msg, lm, B, X);
295 /* update local pointers */
300 SET_COUNTER(A, L, 0, counter_tmp);
301 rijndael_encrypt(ctx, A, S);
305 /* return length if MAC is valid, otherwise continue with error handling */
306 if (equals(X, msg, M))