Line | Count | Source (jump to first uncovered line) |
1 | | /* ccm.c |
2 | | |
3 | | Counter with CBC-MAC mode, specified by NIST, |
4 | | http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf |
5 | | |
6 | | Copyright (C) 2014 Exegin Technologies Limited |
7 | | Copyright (C) 2014 Owen Kirby |
8 | | |
9 | | This file is part of GNU Nettle. |
10 | | |
11 | | GNU Nettle is free software: you can redistribute it and/or |
12 | | modify it under the terms of either: |
13 | | |
14 | | * the GNU Lesser General Public License as published by the Free |
15 | | Software Foundation; either version 3 of the License, or (at your |
16 | | option) any later version. |
17 | | |
18 | | or |
19 | | |
20 | | * the GNU General Public License as published by the Free |
21 | | Software Foundation; either version 2 of the License, or (at your |
22 | | option) any later version. |
23 | | |
24 | | or both in parallel, as here. |
25 | | |
26 | | GNU Nettle is distributed in the hope that it will be useful, |
27 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
28 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
29 | | General Public License for more details. |
30 | | |
31 | | You should have received copies of the GNU General Public License and |
32 | | the GNU Lesser General Public License along with this program. If |
33 | | not, see http://www.gnu.org/licenses/. |
34 | | */ |
35 | | |
36 | | #if HAVE_CONFIG_H |
37 | | # include "config.h" |
38 | | #endif |
39 | | |
40 | | #include <assert.h> |
41 | | #include <stdlib.h> |
42 | | #include <string.h> |
43 | | |
44 | | #include "ccm.h" |
45 | | #include "ctr.h" |
46 | | |
47 | | #include "memops.h" |
48 | | #include "nettle-internal.h" |
49 | | #include "macros.h" |
50 | | |
51 | | /* |
52 | | * The format of the CCM IV (for both CTR and CBC-MAC) is: flags | nonce | count |
53 | | * flags = 1 octet |
54 | | * nonce = N octets |
55 | | * count >= 1 octet |
56 | | * |
57 | | * such that: |
58 | | * sizeof(flags) + sizeof(nonce) + sizeof(count) == 1 block |
59 | | */ |
60 | 0 | #define CCM_FLAG_L 0x07 |
61 | 0 | #define CCM_FLAG_M 0x38 |
62 | 0 | #define CCM_FLAG_ADATA 0x40 |
63 | | #define CCM_FLAG_RESERVED 0x80 |
64 | 0 | #define CCM_FLAG_GET_L(_x_) (((_x_) & CCM_FLAG_L) + 1) |
65 | 0 | #define CCM_FLAG_SET_L(_x_) (((_x_) - 1) & CCM_FLAG_L) |
66 | 0 | #define CCM_FLAG_SET_M(_x_) ((((_x_) - 2) << 2) & CCM_FLAG_M) |
67 | | |
68 | 0 | #define CCM_OFFSET_FLAGS 0 |
69 | 0 | #define CCM_OFFSET_NONCE 1 |
70 | | #define CCM_L_SIZE(_nlen_) (CCM_BLOCK_SIZE - CCM_OFFSET_NONCE - (_nlen_)) |
71 | | |
72 | | /* |
73 | | * The data input to the CBC-MAC: L(a) | adata | padding | plaintext | padding |
74 | | * |
75 | | * blength is the length of data that has been added to the CBC-MAC modulus the |
76 | | * cipher block size. If the value of blength is non-zero then some data has |
77 | | * been XOR'ed into the CBC-MAC, and we will need to pad the block (XOR with 0), |
78 | | * and iterate the cipher one more time. |
79 | | * |
80 | | * The end of adata is detected implicitly by the first call to the encrypt() |
81 | | * and decrypt() functions, and will call ccm_pad() to insert the padding if |
82 | | * necessary. Because of the underlying CTR encryption, the encrypt() and |
83 | | * decrypt() functions must be called with a multiple of the block size and |
84 | | * therefore blength should be zero on all but the first call. |
85 | | * |
86 | | * Likewise, the end of the plaintext is implicitly determined by the first call |
87 | | * to the digest() function, which will pad if the final CTR encryption was not |
88 | | * a multiple of the block size. |
89 | | */ |
90 | | static void |
91 | | ccm_pad(struct ccm_ctx *ctx, const void *cipher, nettle_cipher_func *f) |
92 | 0 | { |
93 | 0 | if (ctx->blength) f(cipher, CCM_BLOCK_SIZE, ctx->tag.b, ctx->tag.b); |
94 | 0 | ctx->blength = 0; |
95 | 0 | } |
96 | | |
97 | | static void |
98 | | ccm_build_iv(uint8_t *iv, size_t noncelen, const uint8_t *nonce, |
99 | | uint8_t flags, size_t count) |
100 | 0 | { |
101 | 0 | unsigned int i; |
102 | | |
103 | | /* Sanity check the nonce length. */ |
104 | 0 | assert(noncelen >= CCM_MIN_NONCE_SIZE); |
105 | 0 | assert(noncelen <= CCM_MAX_NONCE_SIZE); |
106 | | |
107 | | /* Generate the IV */ |
108 | 0 | iv[CCM_OFFSET_FLAGS] = flags | CCM_FLAG_SET_L(CCM_L_SIZE(noncelen)); |
109 | 0 | memcpy(&iv[CCM_OFFSET_NONCE], nonce, noncelen); |
110 | 0 | for (i=(CCM_BLOCK_SIZE - 1); i >= (CCM_OFFSET_NONCE + noncelen); i--) { |
111 | 0 | iv[i] = count & 0xff; |
112 | 0 | count >>= 8; |
113 | 0 | } |
114 | | |
115 | | /* Ensure the count was not truncated. */ |
116 | 0 | assert(!count); |
117 | 0 | } |
118 | | |
119 | | void |
120 | | ccm_set_nonce(struct ccm_ctx *ctx, const void *cipher, nettle_cipher_func *f, |
121 | | size_t length, const uint8_t *nonce, |
122 | | size_t authlen, size_t msglen, size_t taglen) |
123 | 0 | { |
124 | | /* Generate the IV for the CTR and CBC-MAC */ |
125 | 0 | ctx->blength = 0; |
126 | 0 | ccm_build_iv(ctx->tag.b, length, nonce, CCM_FLAG_SET_M(taglen), msglen); |
127 | 0 | ccm_build_iv(ctx->ctr.b, length, nonce, 0, 1); |
128 | | |
129 | | /* If no auth data, encrypt B0 and skip L(a) */ |
130 | 0 | if (!authlen) { |
131 | 0 | f(cipher, CCM_BLOCK_SIZE, ctx->tag.b, ctx->tag.b); |
132 | 0 | return; |
133 | 0 | } |
134 | | |
135 | | /* Encrypt B0 (with the adata flag), and input L(a) to the CBC-MAC. */ |
136 | 0 | ctx->tag.b[CCM_OFFSET_FLAGS] |= CCM_FLAG_ADATA; |
137 | 0 | f(cipher, CCM_BLOCK_SIZE, ctx->tag.b, ctx->tag.b); |
138 | 0 | #if SIZEOF_SIZE_T > 4 |
139 | 0 | if (authlen >= (0x01ULL << 32)) { |
140 | | /* Encode L(a) as 0xff || 0xff || <64-bit integer> */ |
141 | 0 | ctx->tag.b[ctx->blength++] ^= 0xff; |
142 | 0 | ctx->tag.b[ctx->blength++] ^= 0xff; |
143 | 0 | ctx->tag.b[ctx->blength++] ^= (authlen >> 56) & 0xff; |
144 | 0 | ctx->tag.b[ctx->blength++] ^= (authlen >> 48) & 0xff; |
145 | 0 | ctx->tag.b[ctx->blength++] ^= (authlen >> 40) & 0xff; |
146 | 0 | ctx->tag.b[ctx->blength++] ^= (authlen >> 32) & 0xff; |
147 | 0 | ctx->tag.b[ctx->blength++] ^= (authlen >> 24) & 0xff; |
148 | 0 | ctx->tag.b[ctx->blength++] ^= (authlen >> 16) & 0xff; |
149 | 0 | } |
150 | 0 | else |
151 | 0 | #endif |
152 | 0 | if (authlen >= ((0x1ULL << 16) - (0x1ULL << 8))) { |
153 | | /* Encode L(a) as 0xff || 0xfe || <32-bit integer> */ |
154 | 0 | ctx->tag.b[ctx->blength++] ^= 0xff; |
155 | 0 | ctx->tag.b[ctx->blength++] ^= 0xfe; |
156 | 0 | ctx->tag.b[ctx->blength++] ^= (authlen >> 24) & 0xff; |
157 | 0 | ctx->tag.b[ctx->blength++] ^= (authlen >> 16) & 0xff; |
158 | 0 | } |
159 | 0 | ctx->tag.b[ctx->blength++] ^= (authlen >> 8) & 0xff; |
160 | 0 | ctx->tag.b[ctx->blength++] ^= (authlen >> 0) & 0xff; |
161 | 0 | } |
162 | | |
163 | | void |
164 | | ccm_update(struct ccm_ctx *ctx, const void *cipher, nettle_cipher_func *f, |
165 | | size_t length, const uint8_t *data) |
166 | 0 | { |
167 | 0 | const uint8_t *end = data + length; |
168 | | |
169 | | /* If we don't have enough to fill a block, save the data for later. */ |
170 | 0 | if ((ctx->blength + length) < CCM_BLOCK_SIZE) { |
171 | 0 | memxor(&ctx->tag.b[ctx->blength], data, length); |
172 | 0 | ctx->blength += length; |
173 | 0 | return; |
174 | 0 | } |
175 | | |
176 | | /* Process a partially filled block. */ |
177 | 0 | if (ctx->blength) { |
178 | 0 | memxor(&ctx->tag.b[ctx->blength], data, CCM_BLOCK_SIZE - ctx->blength); |
179 | 0 | data += (CCM_BLOCK_SIZE - ctx->blength); |
180 | 0 | f(cipher, CCM_BLOCK_SIZE, ctx->tag.b, ctx->tag.b); |
181 | 0 | } |
182 | | |
183 | | /* Process full blocks. */ |
184 | 0 | while ((data + CCM_BLOCK_SIZE) < end) { |
185 | 0 | memxor(ctx->tag.b, data, CCM_BLOCK_SIZE); |
186 | 0 | f(cipher, CCM_BLOCK_SIZE, ctx->tag.b, ctx->tag.b); |
187 | 0 | data += CCM_BLOCK_SIZE; |
188 | 0 | } /* while */ |
189 | | |
190 | | /* Save leftovers for later. */ |
191 | 0 | ctx->blength = (end - data); |
192 | 0 | if (ctx->blength) memxor(&ctx->tag.b, data, ctx->blength); |
193 | 0 | } |
194 | | |
195 | | /* |
196 | | * Because of the underlying CTR mode encryption, when called multiple times |
197 | | * the data in intermediate calls must be provided in multiples of the block |
198 | | * size. |
199 | | */ |
200 | | void |
201 | | ccm_encrypt(struct ccm_ctx *ctx, const void *cipher, nettle_cipher_func *f, |
202 | | size_t length, uint8_t *dst, const uint8_t *src) |
203 | 0 | { |
204 | 0 | ccm_pad(ctx, cipher, f); |
205 | 0 | ccm_update(ctx, cipher, f, length, src); |
206 | 0 | ctr_crypt(cipher, f, CCM_BLOCK_SIZE, ctx->ctr.b, length, dst, src); |
207 | 0 | } |
208 | | |
209 | | /* |
210 | | * Because of the underlying CTR mode decryption, when called multiple times |
211 | | * the data in intermediate calls must be provided in multiples of the block |
212 | | * size. |
213 | | */ |
214 | | void |
215 | | ccm_decrypt(struct ccm_ctx *ctx, const void *cipher, nettle_cipher_func *f, |
216 | | size_t length, uint8_t *dst, const uint8_t *src) |
217 | 0 | { |
218 | 0 | ctr_crypt(cipher, f, CCM_BLOCK_SIZE, ctx->ctr.b, length, dst, src); |
219 | 0 | ccm_pad(ctx, cipher, f); |
220 | 0 | ccm_update(ctx, cipher, f, length, dst); |
221 | 0 | } |
222 | | |
223 | | void |
224 | | ccm_digest(struct ccm_ctx *ctx, const void *cipher, nettle_cipher_func *f, |
225 | | size_t length, uint8_t *digest) |
226 | 0 | { |
227 | 0 | int i = CCM_BLOCK_SIZE - CCM_FLAG_GET_L(ctx->ctr.b[CCM_OFFSET_FLAGS]); |
228 | 0 | assert(length <= CCM_BLOCK_SIZE); |
229 | 0 | while (i < CCM_BLOCK_SIZE) ctx->ctr.b[i++] = 0; |
230 | 0 | ccm_pad(ctx, cipher, f); |
231 | 0 | ctr_crypt(cipher, f, CCM_BLOCK_SIZE, ctx->ctr.b, length, digest, ctx->tag.b); |
232 | 0 | } |
233 | | |
234 | | void |
235 | | ccm_encrypt_message(const void *cipher, nettle_cipher_func *f, |
236 | | size_t nlength, const uint8_t *nonce, |
237 | | size_t alength, const uint8_t *adata, size_t tlength, |
238 | | size_t clength, uint8_t *dst, const uint8_t *src) |
239 | 0 | { |
240 | 0 | struct ccm_ctx ctx; |
241 | 0 | uint8_t *tag = dst + (clength-tlength); |
242 | 0 | assert(clength >= tlength); |
243 | 0 | ccm_set_nonce(&ctx, cipher, f, nlength, nonce, alength, clength-tlength, tlength); |
244 | 0 | ccm_update(&ctx, cipher, f, alength, adata); |
245 | 0 | ccm_encrypt(&ctx, cipher, f, clength-tlength, dst, src); |
246 | 0 | ccm_digest(&ctx, cipher, f, tlength, tag); |
247 | 0 | } |
248 | | |
249 | | int |
250 | | ccm_decrypt_message(const void *cipher, nettle_cipher_func *f, |
251 | | size_t nlength, const uint8_t *nonce, |
252 | | size_t alength, const uint8_t *adata, size_t tlength, |
253 | | size_t mlength, uint8_t *dst, const uint8_t *src) |
254 | 0 | { |
255 | 0 | struct ccm_ctx ctx; |
256 | 0 | uint8_t tag[CCM_BLOCK_SIZE]; |
257 | 0 | ccm_set_nonce(&ctx, cipher, f, nlength, nonce, alength, mlength, tlength); |
258 | 0 | ccm_update(&ctx, cipher, f, alength, adata); |
259 | 0 | ccm_decrypt(&ctx, cipher, f, mlength, dst, src); |
260 | 0 | ccm_digest(&ctx, cipher, f, tlength, tag); |
261 | 0 | return memeql_sec(tag, src + mlength, tlength); |
262 | 0 | } |