ced0a2b5d73bb247b6b370b3e22ab8353889de6a
[openssl.git] / crypto / modes / ccm128.c
1 /* ====================================================================
2  * Copyright (c) 2011 The OpenSSL Project.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer. 
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in
13  *    the documentation and/or other materials provided with the
14  *    distribution.
15  *
16  * 3. All advertising materials mentioning features or use of this
17  *    software must display the following acknowledgment:
18  *    "This product includes software developed by the OpenSSL Project
19  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
20  *
21  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22  *    endorse or promote products derived from this software without
23  *    prior written permission. For written permission, please contact
24  *    openssl-core@openssl.org.
25  *
26  * 5. Products derived from this software may not be called "OpenSSL"
27  *    nor may "OpenSSL" appear in their names without prior written
28  *    permission of the OpenSSL Project.
29  *
30  * 6. Redistributions of any form whatsoever must retain the following
31  *    acknowledgment:
32  *    "This product includes software developed by the OpenSSL Project
33  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
34  *
35  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46  * OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  */
49
50 #include <openssl/crypto.h>
51 #include "modes_lcl.h"
52 #include <string.h>
53
54 #ifndef MODES_DEBUG
55 # ifndef NDEBUG
56 #  define NDEBUG
57 # endif
58 #endif
59 #include <assert.h>
60
61 typedef struct {
62         union { u8 c[16]; size_t s[16/sizeof(size_t)]; } nonce, cmac,
63                                                          scratch, inp;
64         u64 blocks;
65         block128_f block;
66         void *key;
67 } CCM128_CONTEXT;
68
69 /* First you setup M and L parameters and pass the key schedule */
70 void CRYPTO_ccm128_init(CCM128_CONTEXT *ctx,
71         unsigned int M,unsigned int L,void *key,block128_f block)
72 {
73         memset(ctx->nonce.c,0,sizeof(ctx->nonce.c));
74         ctx->nonce.c[0] = ((u8)(L-1)&7) | (u8)(((M-2)/2)&7)<<3;
75         ctx->blocks = 0;
76         ctx->block = block;
77         ctx->key = key;
78 }
79
80 /* !!! Following interfaces are to be called *once* per packet !!! */
81
82 /* Then you setup per-message nonce and pass the length of the message */
83 int CRYPTO_ccm128_setiv(CCM128_CONTEXT *ctx,
84         const unsigned char *nonce,size_t nlen,size_t mlen)
85 {
86         unsigned int L = ctx->nonce.c[0]&7;     /* the L parameter */
87
88         if (nlen<(14-L)) return -1;             /* nonce is too short */
89
90         if (sizeof(mlen)==8 && L>=3) {
91                 ctx->nonce.c[8]  = (u8)(mlen>>(56%(sizeof(mlen)*8)));
92                 ctx->nonce.c[9]  = (u8)(mlen>>(48%(sizeof(mlen)*8)));
93                 ctx->nonce.c[10] = (u8)(mlen>>(40%(sizeof(mlen)*8)));
94                 ctx->nonce.c[11] = (u8)(mlen>>(32%(sizeof(mlen)*8)));
95         }
96         else
97                 *((size_t *)&ctx->nonce.s[8]) = 0;
98
99         ctx->nonce.c[12] = (u8)(mlen>>24);
100         ctx->nonce.c[13] = (u8)(mlen>>16);
101         ctx->nonce.c[14] = (u8)(mlen>>8);
102         ctx->nonce.c[15] = (u8)mlen;
103
104         ctx->nonce.c[0] &= ~0x40;       /* clear Adata flag */
105         memcpy(&ctx->nonce.c[1],nonce,14-L);
106
107         return 0;
108 }
109
110 /* Then you pass additional authentication data, this is optional */
111 void CRYPTO_ccm128_aad(CCM128_CONTEXT *ctx,
112         const unsigned char *aad,size_t alen)
113 {       unsigned int i;
114
115         if (alen==0) return;
116
117         ctx->nonce.c[0] |= 0x40;        /* set Adata flag */
118         (*ctx->block)(ctx->nonce.c,ctx->cmac.c,ctx->key),
119         ctx->blocks++;
120
121         if (alen<(0x10000-0x100)) {
122                 ctx->cmac.c[0] ^= (u8)(alen>>8);
123                 ctx->cmac.c[1] ^= (u8)alen;
124                 i=2;
125         }
126         else if (sizeof(alen)==8 && alen>=(size_t)1<<32) {
127                 ctx->cmac.c[0] ^= 0xFF;
128                 ctx->cmac.c[1] ^= 0xFF;
129                 ctx->cmac.c[2] ^= (u8)(alen>>(56%(sizeof(alen)*8)));
130                 ctx->cmac.c[3] ^= (u8)(alen>>(48%(sizeof(alen)*8)));
131                 ctx->cmac.c[4] ^= (u8)(alen>>(40%(sizeof(alen)*8)));
132                 ctx->cmac.c[5] ^= (u8)(alen>>(32%(sizeof(alen)*8)));
133                 ctx->cmac.c[6] ^= (u8)(alen>>24);
134                 ctx->cmac.c[7] ^= (u8)(alen>>16);
135                 ctx->cmac.c[8] ^= (u8)(alen>>8);
136                 ctx->cmac.c[9] ^= (u8)alen;
137                 i=10;
138         }
139         else {
140                 ctx->cmac.c[0] ^= 0xFF;
141                 ctx->cmac.c[1] ^= 0xFE;
142                 ctx->cmac.c[2] ^= (u8)(alen>>24);
143                 ctx->cmac.c[3] ^= (u8)(alen>>16);
144                 ctx->cmac.c[4] ^= (u8)(alen>>8);
145                 ctx->cmac.c[5] ^= (u8)alen;
146                 i=6;
147         }
148
149         do {
150                 for(;i<16 && alen;++i,++aad,--alen)
151                         ctx->cmac.c[i] ^= *aad;
152                 (*ctx->block)(ctx->cmac.c,ctx->cmac.c,ctx->key),
153                 ctx->blocks++;
154                 i=0;
155         } while (alen);
156 }
157
158 /* Finally you encrypt or decrypt the message */
159
160 static void ctr128_inc(unsigned char *counter) {
161         unsigned int n=16;
162         u8  c;
163
164         do {
165                 --n;
166                 c = counter[n];
167                 ++c;
168                 counter[n] = c;
169                 if (c) return;
170         } while (n);
171 }
172
173 int CRYPTO_ccm128_encrypt(CCM128_CONTEXT *ctx,
174         const unsigned char *inp, unsigned char *out,
175         size_t len)
176 {
177         size_t          n;
178         unsigned int    i;
179         unsigned char   flags = ctx->nonce.c[0];
180
181         if (!(flags&0x40))
182                 (*ctx->block)(ctx->nonce.c,ctx->cmac.c,ctx->key),
183                 ctx->blocks++;
184
185         flags &= 7;     /* extract the L parameter */
186         for (n=0,i=15-flags;i<15;++i) {
187                 n |= ctx->nonce.c[i]; ctx->nonce.c[i]=0;
188                 n <<= 8;
189         }
190         n |= ctx->nonce.c[15];  /* reconstructed length */
191         ctx->nonce.c[15]=1;
192
193         if (n!=len) return -1;  /* length mismatch */
194
195         ctx->blocks += ((len+15)>>3)|1;
196         if (ctx->blocks > (U64(1)<<61)) return -2; /* too much data */
197
198         while (len>=16) {
199 #if defined(STRICT_ALIGNMENT)
200                 memcpy (ctx->inp.c,inp,16);
201                 for (i=0; i<16/sizeof(size_t); ++i)
202                         ctx->cmac.s[i] ^= ctx->inp.s[i];
203 #else
204                 for (i=0; i<16/sizeof(size_t); ++i)
205                         ctx->cmac.s[i] ^= ((size_t*)inp)[i];
206 #endif
207                 (*ctx->block)(ctx->cmac.c,ctx->cmac.c,ctx->key);
208                 (*ctx->block)(ctx->nonce.c,ctx->scratch.c,ctx->key);
209                 ctr128_inc(ctx->nonce.c);
210 #if defined(STRICT_ALIGNMENT)
211                 for (i=0; i<16/sizeof(size_t); ++i)
212                         ctx->inp.s[i] ^= ctx->scratch.s[i];
213                 memcpy(out,ctx->inp.c,16);
214 #else
215                 for (i=0; i<16/sizeof(size_t); ++i)
216                         ((size_t*)out)[i] = ctx->scratch.s[i]^((size_t*)inp)[i];
217 #endif
218                 inp += 16;
219                 out += 16;
220                 len -= 16;
221         }
222
223         if (len) {
224                 for (i=0; i<len; ++i) ctx->cmac.c[i] ^= inp[i];
225                 (*ctx->block)(ctx->cmac.c,ctx->cmac.c,ctx->key);
226                 (*ctx->block)(ctx->nonce.c,ctx->scratch.c,ctx->key);
227                 for (i=0; i<len; ++i) out[i] = ctx->scratch.c[i]^inp[i];
228         }
229
230         for (i=15-flags;i<16;++i)
231                 ctx->nonce.c[i]=0;
232
233         (*ctx->block)(ctx->nonce.c,ctx->scratch.c,ctx->key);
234         for (i=0; i<16/sizeof(size_t); ++i)
235                 ctx->cmac.s[i] ^= ctx->scratch.s[i];
236
237         return 0;
238 }
239
240 int CRYPTO_ccm128_decrypt(CCM128_CONTEXT *ctx,
241         const unsigned char *inp, unsigned char *out,
242         size_t len)
243 {
244         size_t          n;
245         unsigned int    i;
246         unsigned char   flags = ctx->nonce.c[0];
247
248         if (!(flags&0x40))
249                 (*ctx->block)(ctx->nonce.c,ctx->cmac.c,ctx->key);
250
251         flags &= 7;     /* extract the L parameter */
252         for (n=0,i=15-flags;i<15;++i) {
253                 n |= ctx->nonce.c[i]; ctx->nonce.c[i]=0;
254                 n <<= 8;
255         }
256         n |= ctx->nonce.c[15];  /* reconstructed length */
257         ctx->nonce.c[15]=1;
258
259         if (n!=len) return -1;
260
261         while (len>=16) {
262                 (*ctx->block)(ctx->nonce.c,ctx->scratch.c,ctx->key);
263                 ctr128_inc(ctx->nonce.c);
264 #if defined(STRICT_ALIGNMENT)
265                 memcpy (ctx->inp.c,inp,16);
266                 for (i=0; i<16/sizeof(size_t); ++i)
267                         ctx->cmac.s[i] ^= (ctx->scratch.s[i] ^= ctx->inp.s[i]);
268                 memcpy (out,ctx->scratch,16);
269 #else
270                 for (i=0; i<16/sizeof(size_t); ++i)
271                         ctx->cmac.s[i] ^= ((size_t*)out)[i] = ctx->scratch.s[i]^((size_t*)inp)[i];
272 #endif
273                 (*ctx->block)(ctx->cmac.c,ctx->cmac.c,ctx->key);
274
275                 inp += 16;
276                 out += 16;
277                 len -= 16;
278         }
279
280         if (len) {
281                 (*ctx->block)(ctx->nonce.c,ctx->scratch.c,ctx->key);
282                 for (i=0; i<len; ++len)
283                         ctx->cmac.c[i] ^= (out[i] = ctx->scratch.c[i]^inp[i]);
284                 (*ctx->block)(ctx->cmac.c,ctx->cmac.c,ctx->key);
285         }
286
287         for (i=15-flags;i<16;++i)
288                 ctx->nonce.c[i]=0;
289
290         (*ctx->block)(ctx->nonce.c,ctx->scratch.c,ctx->key);
291         for (i=0; i<16/sizeof(size_t); ++i)
292                 ctx->cmac.s[i] ^= ctx->scratch.s[i];
293
294         return 0;
295 }
296
297 size_t CRYPTO_ccm128_tag(CCM128_CONTEXT *ctx,unsigned char *tag,size_t len)
298 {       unsigned int M = (ctx->nonce.c[0]>>3)&7;        /* the M parameter */
299
300         M *= 2; M += 2;
301         if (len<M)      return 0;
302         memcpy(tag,ctx->cmac.c,M);
303         return M;
304 }