1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
53
54
55
56
57
58
59
60
61
64
65
85
86
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
112
113
114
115
116
117
118
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
153
154
155
156
157
158
159
160
161
162
165
166
167
168
169
170
173
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
214
215
216
217
218
219
220
221
222
223
226
227
228
229
230
231
232
233
234
235
238
239
240
241
242
243
246
247
248
249
250
251
254
257
258
259
266
/* ... */
#include <tinycrypt/ccm_mode.h>
#include <tinycrypt/constants.h>
#include <tinycrypt/utils.h>
#include <stdio.h>
int tc_ccm_config(TCCcmMode_t c, TCAesKeySched_t sched, uint8_t *nonce,
unsigned int nlen, unsigned int mlen)
{
if (c == (TCCcmMode_t) 0 ||
sched == (TCAesKeySched_t) 0 ||
nonce == (uint8_t *) 0) {
return TC_CRYPTO_FAIL;
}{...} else if (nlen != 13) {
return TC_CRYPTO_FAIL;
}{...} else if ((mlen < 4) || (mlen > 16) || (mlen & 1)) {
return TC_CRYPTO_FAIL;
}{...}
c->mlen = mlen;
c->sched = sched;
c->nonce = nonce;
return TC_CRYPTO_SUCCESS;
}{ ... }
/* ... */
static void ccm_cbc_mac(uint8_t *T, const uint8_t *data, unsigned int dlen,
unsigned int flag, TCAesKeySched_t sched)
{
unsigned int i;
if (flag > 0) {
T[0] ^= (uint8_t)(dlen >> 8);
T[1] ^= (uint8_t)(dlen);
dlen += 2; i = 2;
}{...} else {
i = 0;
}{...}
while (i < dlen) {
T[i++ % (Nb * Nk)] ^= *data++;
if (((i % (Nb * Nk)) == 0) || dlen == i) {
(void) tc_aes_encrypt(T, T, sched);
}{...}
}{...}
}{ ... }
/* ... */
static int ccm_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in,
unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched)
{
uint8_t buffer[TC_AES_BLOCK_SIZE];
uint8_t nonce[TC_AES_BLOCK_SIZE];
uint16_t block_num;
unsigned int i;
if (out == (uint8_t *) 0 ||
in == (uint8_t *) 0 ||
ctr == (uint8_t *) 0 ||
sched == (TCAesKeySched_t) 0 ||
inlen == 0 ||
outlen == 0 ||
outlen != inlen) {
return TC_CRYPTO_FAIL;
}{...}
(void) _copy(nonce, sizeof(nonce), ctr, sizeof(nonce));
block_num = (uint16_t) ((nonce[14] << 8)|(nonce[15]));
for (i = 0; i < inlen; ++i) {
if ((i % (TC_AES_BLOCK_SIZE)) == 0) {
block_num++;
nonce[14] = (uint8_t)(block_num >> 8);
nonce[15] = (uint8_t)(block_num);
if (!tc_aes_encrypt(buffer, nonce, sched)) {
return TC_CRYPTO_FAIL;
}{...}
}{...}
*out++ = buffer[i % (TC_AES_BLOCK_SIZE)] ^ *in++;
}{...}
ctr[14] = nonce[14]; ctr[15] = nonce[15];
return TC_CRYPTO_SUCCESS;
}{ ... }
int tc_ccm_generation_encryption(uint8_t *out, unsigned int olen,
const uint8_t *associated_data,
unsigned int alen, const uint8_t *payload,
unsigned int plen, TCCcmMode_t c)
{
if ((out == (uint8_t *) 0) ||
(c == (TCCcmMode_t) 0) ||
((plen > 0) && (payload == (uint8_t *) 0)) ||
((alen > 0) && (associated_data == (uint8_t *) 0)) ||
(alen >= TC_CCM_AAD_MAX_BYTES) ||
(plen >= TC_CCM_PAYLOAD_MAX_BYTES) ||
(olen < (plen + c->mlen))) {
return TC_CRYPTO_FAIL;
}{...}
uint8_t b[Nb * Nk];
uint8_t tag[Nb * Nk];
unsigned int i;
b[0] = ((alen > 0) ? 0x40:0) | (((c->mlen - 2) / 2 << 3)) | (1);
for (i = 1; i <= 13; ++i) {
b[i] = c->nonce[i - 1];
}{...}
b[14] = (uint8_t)(plen >> 8);
b[15] = (uint8_t)(plen);
(void) tc_aes_encrypt(tag, b, c->sched);
if (alen > 0) {
ccm_cbc_mac(tag, associated_data, alen, 1, c->sched);
}{...}
if (plen > 0) {
ccm_cbc_mac(tag, payload, plen, 0, c->sched);
}{...}
b[0] = 1;
b[14] = b[15] = TC_ZERO_BYTE;
ccm_ctr_mode(out, plen, payload, plen, b, c->sched);
b[14] = b[15] = TC_ZERO_BYTE;
(void) tc_aes_encrypt(b, b, c->sched);
out += plen;
for (i = 0; i < c->mlen; ++i) {
*out++ = tag[i] ^ b[i];
}{...}
return TC_CRYPTO_SUCCESS;
}{ ... }
int tc_ccm_decryption_verification(uint8_t *out, unsigned int olen,
const uint8_t *associated_data,
unsigned int alen, const uint8_t *payload,
unsigned int plen, TCCcmMode_t c)
{
if ((out == (uint8_t *) 0) ||
(c == (TCCcmMode_t) 0) ||
((plen > 0) && (payload == (uint8_t *) 0)) ||
((alen > 0) && (associated_data == (uint8_t *) 0)) ||
(alen >= TC_CCM_AAD_MAX_BYTES) ||
(plen >= TC_CCM_PAYLOAD_MAX_BYTES) ||
(olen < plen - c->mlen)) {
return TC_CRYPTO_FAIL;
}{...}
uint8_t b[Nb * Nk];
uint8_t tag[Nb * Nk];
unsigned int i;
b[0] = 1;
for (i = 1; i < 14; ++i) {
b[i] = c->nonce[i - 1];
}{...}
b[14] = b[15] = TC_ZERO_BYTE;
ccm_ctr_mode(out, plen - c->mlen, payload, plen - c->mlen, b, c->sched);
b[14] = b[15] = TC_ZERO_BYTE;
(void) tc_aes_encrypt(b, b, c->sched);
for (i = 0; i < c->mlen; ++i) {
tag[i] = *(payload + plen - c->mlen + i) ^ b[i];
}{...}
b[0] = ((alen > 0) ? 0x40:0)|(((c->mlen - 2) / 2 << 3)) | (1);
for (i = 1; i < 14; ++i) {
b[i] = c->nonce[i - 1];
}{...}
b[14] = (uint8_t)((plen - c->mlen) >> 8);
b[15] = (uint8_t)(plen - c->mlen);
(void) tc_aes_encrypt(b, b, c->sched);
if (alen > 0) {
ccm_cbc_mac(b, associated_data, alen, 1, c->sched);
}{...}
if (plen > 0) {
ccm_cbc_mac(b, out, plen - c->mlen, 0, c->sched);
}{...}
if (_compare(b, tag, c->mlen) == 0) {
return TC_CRYPTO_SUCCESS;
}{...} else {
_set(out, 0, plen - c->mlen);
return TC_CRYPTO_FAIL;
}{...}
}{ ... }