/src/nettle-with-libgmp/ccm.c
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  | 2.25k  | #define CCM_FLAG_L          0x07  | 
61  | 752  | #define CCM_FLAG_M          0x38  | 
62  | 460  | #define CCM_FLAG_ADATA      0x40  | 
63  |  | #define CCM_FLAG_RESERVED   0x80  | 
64  | 752  | #define CCM_FLAG_GET_L(_x_) (((_x_) & CCM_FLAG_L) + 1)  | 
65  | 1.50k  | #define CCM_FLAG_SET_L(_x_) (((_x_) - 1) & CCM_FLAG_L)  | 
66  | 752  | #define CCM_FLAG_SET_M(_x_) ((((_x_) - 2) << 2) & CCM_FLAG_M)  | 
67  |  |  | 
68  | 1.96k  | #define CCM_OFFSET_FLAGS    0  | 
69  | 9.97k  | #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  | 8.63k  | { | 
93  | 8.63k  |     if (ctx->blength) f(cipher, CCM_BLOCK_SIZE, ctx->tag.b, ctx->tag.b);  | 
94  | 8.63k  |     ctx->blength = 0;  | 
95  | 8.63k  | }  | 
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  | 1.50k  | { | 
101  | 1.50k  |   unsigned int i;  | 
102  |  |  | 
103  |  |   /* Sanity check the nonce length. */  | 
104  | 1.50k  |   assert(noncelen >= CCM_MIN_NONCE_SIZE);  | 
105  | 1.50k  |   assert(noncelen <= CCM_MAX_NONCE_SIZE);  | 
106  |  |  | 
107  |  |   /* Generate the IV */  | 
108  | 1.50k  |   iv[CCM_OFFSET_FLAGS] = flags | CCM_FLAG_SET_L(CCM_L_SIZE(noncelen));  | 
109  | 1.50k  |   memcpy(&iv[CCM_OFFSET_NONCE], nonce, noncelen);  | 
110  | 8.46k  |   for (i=(CCM_BLOCK_SIZE - 1); i >= (CCM_OFFSET_NONCE + noncelen); i--) { | 
111  | 6.96k  |     iv[i] = count & 0xff;  | 
112  | 6.96k  |     count >>= 8;  | 
113  | 6.96k  |   }  | 
114  |  |  | 
115  |  |   /* Ensure the count was not truncated. */  | 
116  | 1.50k  |   assert(!count);  | 
117  | 1.50k  | }  | 
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  | 752  | { | 
124  |  |   /* Generate the IV for the CTR and CBC-MAC */  | 
125  | 752  |   ctx->blength = 0;  | 
126  | 752  |   ccm_build_iv(ctx->tag.b, length, nonce, CCM_FLAG_SET_M(taglen), msglen);  | 
127  | 752  |   ccm_build_iv(ctx->ctr.b, length, nonce, 0, 1);  | 
128  |  |  | 
129  |  |   /* If no auth data, encrypt B0 and skip L(a) */  | 
130  | 752  |   if (!authlen) { | 
131  | 292  |     f(cipher, CCM_BLOCK_SIZE, ctx->tag.b, ctx->tag.b);  | 
132  | 292  |     return;  | 
133  | 292  |   }  | 
134  |  |  | 
135  |  |   /* Encrypt B0 (with the adata flag), and input L(a) to the CBC-MAC. */  | 
136  | 460  |   ctx->tag.b[CCM_OFFSET_FLAGS] |= CCM_FLAG_ADATA;  | 
137  | 460  |   f(cipher, CCM_BLOCK_SIZE, ctx->tag.b, ctx->tag.b);  | 
138  | 460  | #if SIZEOF_SIZE_T > 4  | 
139  | 460  |   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  | 460  |   else  | 
151  | 460  | #endif  | 
152  | 460  |     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  | 460  |   ctx->tag.b[ctx->blength++] ^= (authlen >> 8) & 0xff;  | 
160  | 460  |   ctx->tag.b[ctx->blength++] ^= (authlen >> 0) & 0xff;  | 
161  | 460  | }  | 
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  | 8.66k  | { | 
167  | 8.66k  |   const uint8_t *end = data + length;  | 
168  |  |  | 
169  |  |   /* If we don't have enough to fill a block, save the data for later. */  | 
170  | 8.66k  |   if ((ctx->blength + length) < CCM_BLOCK_SIZE) { | 
171  | 8.11k  |     memxor(&ctx->tag.b[ctx->blength], data, length);  | 
172  | 8.11k  |     ctx->blength += length;  | 
173  | 8.11k  |     return;  | 
174  | 8.11k  |   }  | 
175  |  |  | 
176  |  |   /* Process a partially filled block. */  | 
177  | 548  |   if (ctx->blength) { | 
178  | 73  |     memxor(&ctx->tag.b[ctx->blength], data, CCM_BLOCK_SIZE - ctx->blength);  | 
179  | 73  |     data += (CCM_BLOCK_SIZE - ctx->blength);  | 
180  | 73  |     f(cipher, CCM_BLOCK_SIZE, ctx->tag.b, ctx->tag.b);  | 
181  | 73  |   }  | 
182  |  |  | 
183  |  |   /* Process full blocks. */  | 
184  | 921  |   while ((data + CCM_BLOCK_SIZE) < end) { | 
185  | 373  |     memxor(ctx->tag.b, data, CCM_BLOCK_SIZE);  | 
186  | 373  |     f(cipher, CCM_BLOCK_SIZE, ctx->tag.b, ctx->tag.b);  | 
187  | 373  |     data += CCM_BLOCK_SIZE;  | 
188  | 373  |   } /* while */  | 
189  |  |  | 
190  |  |   /* Save leftovers for later. */  | 
191  | 548  |   ctx->blength = (end - data);  | 
192  | 548  |   if (ctx->blength) memxor(&ctx->tag.b, data, ctx->blength);  | 
193  | 548  | }  | 
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  | 7.42k  | { | 
204  | 7.42k  |   ccm_pad(ctx, cipher, f);  | 
205  | 7.42k  |   ccm_update(ctx, cipher, f, length, src);  | 
206  | 7.42k  |   ctr_crypt(cipher, f, CCM_BLOCK_SIZE, ctx->ctr.b, length, dst, src);  | 
207  | 7.42k  | }  | 
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  | 453  | { | 
218  | 453  |   ctr_crypt(cipher, f, CCM_BLOCK_SIZE, ctx->ctr.b, length, dst, src);  | 
219  | 453  |   ccm_pad(ctx, cipher, f);  | 
220  | 453  |   ccm_update(ctx, cipher, f, length, dst);  | 
221  | 453  | }  | 
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  | 752  | { | 
227  | 752  |   int i = CCM_BLOCK_SIZE - CCM_FLAG_GET_L(ctx->ctr.b[CCM_OFFSET_FLAGS]);  | 
228  | 752  |   assert(length <= CCM_BLOCK_SIZE);  | 
229  | 4.23k  |   while (i < CCM_BLOCK_SIZE)  ctx->ctr.b[i++] = 0;  | 
230  | 752  |   ccm_pad(ctx, cipher, f);  | 
231  | 752  |   ctr_crypt(cipher, f, CCM_BLOCK_SIZE, ctx->ctr.b, length, digest, ctx->tag.b);  | 
232  | 752  | }  | 
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  | }  |