f8746bbf154df110664d1c50dfce7fd70282ddef
[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 /* First you setup M and L parameters and pass the key schedule */
62 void CRYPTO_ccm128_init(CCM128_CONTEXT *ctx,
63         unsigned int M,unsigned int L,void *key,block128_f block)
64 {
65         memset(ctx->nonce.c,0,sizeof(ctx->nonce.c));
66         ctx->nonce.c[0] = ((u8)(L-1)&7) | (u8)(((M-2)/2)&7)<<3;
67         ctx->blocks = 0;
68         ctx->block = block;
69         ctx->key = key;
70 }
71
72 /* !!! Following interfaces are to be called *once* per packet !!! */
73
74 /* Then you setup per-message nonce and pass the length of the message */
75 int CRYPTO_ccm128_setiv(CCM128_CONTEXT *ctx,
76         const unsigned char *nonce,size_t nlen,size_t mlen)
77 {
78         unsigned int L = ctx->nonce.c[0]&7;     /* the L parameter */
79
80         if (nlen<(14-L)) return -1;             /* nonce is too short */
81
82         if (sizeof(mlen)==8 && L>=3) {
83                 ctx->nonce.c[8]  = (u8)(mlen>>(56%(sizeof(mlen)*8)));
84                 ctx->nonce.c[9]  = (u8)(mlen>>(48%(sizeof(mlen)*8)));
85                 ctx->nonce.c[10] = (u8)(mlen>>(40%(sizeof(mlen)*8)));
86                 ctx->nonce.c[11] = (u8)(mlen>>(32%(sizeof(mlen)*8)));
87         }
88         else
89                 *(u32*)(&ctx->nonce.c[8]) = 0;
90
91         ctx->nonce.c[12] = (u8)(mlen>>24);
92         ctx->nonce.c[13] = (u8)(mlen>>16);
93         ctx->nonce.c[14] = (u8)(mlen>>8);
94         ctx->nonce.c[15] = (u8)mlen;
95
96         ctx->nonce.c[0] &= ~0x40;       /* clear Adata flag */
97         memcpy(&ctx->nonce.c[1],nonce,14-L);
98
99         return 0;
100 }
101
102 /* Then you pass additional authentication data, this is optional */
103 void CRYPTO_ccm128_aad(CCM128_CONTEXT *ctx,
104         const unsigned char *aad,size_t alen)
105 {       unsigned int i;
106         block128_f block = ctx->block;
107
108         if (alen==0) return;
109
110         ctx->nonce.c[0] |= 0x40;        /* set Adata flag */
111         (*block)(ctx->nonce.c,ctx->cmac.c,ctx->key),
112         ctx->blocks++;
113
114         if (alen<(0x10000-0x100)) {
115                 ctx->cmac.c[0] ^= (u8)(alen>>8);
116                 ctx->cmac.c[1] ^= (u8)alen;
117                 i=2;
118         }
119         else if (sizeof(alen)==8 && alen>=(size_t)1<<(32%(sizeof(alen)*8))) {
120                 ctx->cmac.c[0] ^= 0xFF;
121                 ctx->cmac.c[1] ^= 0xFF;
122                 ctx->cmac.c[2] ^= (u8)(alen>>(56%(sizeof(alen)*8)));
123                 ctx->cmac.c[3] ^= (u8)(alen>>(48%(sizeof(alen)*8)));
124                 ctx->cmac.c[4] ^= (u8)(alen>>(40%(sizeof(alen)*8)));
125                 ctx->cmac.c[5] ^= (u8)(alen>>(32%(sizeof(alen)*8)));
126                 ctx->cmac.c[6] ^= (u8)(alen>>24);
127                 ctx->cmac.c[7] ^= (u8)(alen>>16);
128                 ctx->cmac.c[8] ^= (u8)(alen>>8);
129                 ctx->cmac.c[9] ^= (u8)alen;
130                 i=10;
131         }
132         else {
133                 ctx->cmac.c[0] ^= 0xFF;
134                 ctx->cmac.c[1] ^= 0xFE;
135                 ctx->cmac.c[2] ^= (u8)(alen>>24);
136                 ctx->cmac.c[3] ^= (u8)(alen>>16);
137                 ctx->cmac.c[4] ^= (u8)(alen>>8);
138                 ctx->cmac.c[5] ^= (u8)alen;
139                 i=6;
140         }
141
142         do {
143                 for(;i<16 && alen;++i,++aad,--alen)
144                         ctx->cmac.c[i] ^= *aad;
145                 (*block)(ctx->cmac.c,ctx->cmac.c,ctx->key),
146                 ctx->blocks++;
147                 i=0;
148         } while (alen);
149 }
150
151 /* Finally you encrypt or decrypt the message */
152
153 static void ctr128_inc(unsigned char *counter) {
154         unsigned int n=16;
155         u8  c;
156
157         do {
158                 --n;
159                 c = counter[n];
160                 ++c;
161                 counter[n] = c;
162                 if (c) return;
163         } while (n);
164 }
165
166 int CRYPTO_ccm128_encrypt(CCM128_CONTEXT *ctx,
167         const unsigned char *inp, unsigned char *out,
168         size_t len)
169 {
170         size_t          n;
171         unsigned int    i,L;
172         unsigned char   flags0 = ctx->nonce.c[0];
173         block128_f      block = ctx->block;
174         union { u64 u[2]; u8 c[16]; } scratch;
175
176         if (!(flags0&0x40))
177                 (*block)(ctx->nonce.c,ctx->cmac.c,ctx->key),
178                 ctx->blocks++;
179
180         ctx->nonce.c[0] = L = flags0&7;
181         for (n=0,i=15-L;i<15;++i) {
182                 n |= ctx->nonce.c[i];
183                 ctx->nonce.c[i]=0;
184                 n <<= 8;
185         }
186         n |= ctx->nonce.c[15];  /* reconstructed length */
187         ctx->nonce.c[15]=1;
188
189         if (n!=len) return -1;  /* length mismatch */
190
191         ctx->blocks += ((len+15)>>3)|1;
192         if (ctx->blocks > (U64(1)<<61)) return -2; /* too much data */
193
194         while (len>=16) {
195 #if defined(STRICT_ALIGNMENT)
196                 union { u64 u[2]; u8 c[16]; } temp;
197
198                 memcpy (temp.c,inp,16);
199                 ctx->cmac.u[0] ^= temp.u[0];
200                 ctx->cmac.u[1] ^= temp.u[1];
201 #else
202                 ctx->cmac.u[0] ^= ((u64*)inp)[0];
203                 ctx->cmac.u[1] ^= ((u64*)inp)[1];
204 #endif
205                 (*block)(ctx->cmac.c,ctx->cmac.c,ctx->key);
206                 (*block)(ctx->nonce.c,scratch.c,ctx->key);
207                 ctr128_inc(ctx->nonce.c);
208 #if defined(STRICT_ALIGNMENT)
209                 temp.u[0] ^= scratch.u[0];
210                 temp.u[1] ^= scratch.u[1];
211                 memcpy(out,temp.c,16);
212 #else
213                 ((u64*)out)[0] = scratch.u[0]^((u64*)inp)[0];
214                 ((u64*)out)[1] = scratch.u[1]^((u64*)inp)[1];
215 #endif
216                 inp += 16;
217                 out += 16;
218                 len -= 16;
219         }
220
221         if (len) {
222                 for (i=0; i<len; ++i) ctx->cmac.c[i] ^= inp[i];
223                 (*block)(ctx->cmac.c,ctx->cmac.c,ctx->key);
224                 (*block)(ctx->nonce.c,scratch.c,ctx->key);
225                 for (i=0; i<len; ++i) out[i] = scratch.c[i]^inp[i];
226         }
227
228         for (i=15-L;i<16;++i)
229                 ctx->nonce.c[i]=0;
230
231         (*block)(ctx->nonce.c,scratch.c,ctx->key);
232         ctx->cmac.u[0] ^= scratch.u[0];
233         ctx->cmac.u[1] ^= scratch.u[1];
234
235         ctx->nonce.c[0] = flags0;
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,L;
246         unsigned char   flags0 = ctx->nonce.c[0];
247         block128_f      block = ctx->block;
248         union { u64 u[2]; u8 c[16]; } scratch;
249
250         if (!(flags0&0x40))
251                 (*block)(ctx->nonce.c,ctx->cmac.c,ctx->key);
252
253         ctx->nonce.c[0] = L = flags0&7;
254         for (n=0,i=15-L;i<15;++i) {
255                 n |= ctx->nonce.c[i];
256                 ctx->nonce.c[i]=0;
257                 n <<= 8;
258         }
259         n |= ctx->nonce.c[15];  /* reconstructed length */
260         ctx->nonce.c[15]=1;
261
262         if (n!=len) return -1;
263
264         while (len>=16) {
265 #if defined(STRICT_ALIGNMENT)
266                 union { u64 u[2]; u8 c[16]; } temp;
267 #endif
268                 (*block)(ctx->nonce.c,scratch.c,ctx->key);
269                 ctr128_inc(ctx->nonce.c);
270 #if defined(STRICT_ALIGNMENT)
271                 memcpy (temp.c,inp,16);
272                 ctx->cmac.u[0] ^= (scratch.u[0] ^= temp.u[0]);
273                 ctx->cmac.u[1] ^= (scratch.u[1] ^= temp.u[1]);
274                 memcpy (out,scratch.c,16);
275 #else
276                 ctx->cmac.u[0] ^= (((u64*)out)[0] = scratch.u[0]^((u64*)inp)[0]);
277                 ctx->cmac.u[1] ^= (((u64*)out)[1] = scratch.u[1]^((u64*)inp)[1]);
278 #endif
279                 (*block)(ctx->cmac.c,ctx->cmac.c,ctx->key);
280
281                 inp += 16;
282                 out += 16;
283                 len -= 16;
284         }
285
286         if (len) {
287                 (*block)(ctx->nonce.c,scratch.c,ctx->key);
288                 for (i=0; i<len; ++len)
289                         ctx->cmac.c[i] ^= (out[i] = scratch.c[i]^inp[i]);
290                 (*block)(ctx->cmac.c,ctx->cmac.c,ctx->key);
291         }
292
293         for (i=15-L;i<16;++i)
294                 ctx->nonce.c[i]=0;
295
296         (*block)(ctx->nonce.c,scratch.c,ctx->key);
297         ctx->cmac.u[0] ^= scratch.u[0];
298         ctx->cmac.u[1] ^= scratch.u[1];
299
300         ctx->nonce.c[0] = flags0;
301
302         return 0;
303 }
304
305 size_t CRYPTO_ccm128_tag(CCM128_CONTEXT *ctx,unsigned char *tag,size_t len)
306 {       unsigned int M = (ctx->nonce.c[0]>>3)&7;        /* the M parameter */
307
308         M *= 2; M += 2;
309         if (len<M)      return 0;
310         memcpy(tag,ctx->cmac.c,M);
311         return M;
312 }