Home | History | Annotate | Download | only in modes
      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 (at) 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  * This is called once per session setup... */
     63 void CRYPTO_ccm128_init(CCM128_CONTEXT *ctx,
     64 	unsigned int M,unsigned int L,void *key,block128_f block)
     65 {
     66 	memset(ctx->nonce.c,0,sizeof(ctx->nonce.c));
     67 	ctx->nonce.c[0] = ((u8)(L-1)&7) | (u8)(((M-2)/2)&7)<<3;
     68 	ctx->blocks = 0;
     69 	ctx->block = block;
     70 	ctx->key = key;
     71 }
     72 
     73 /* !!! Following interfaces are to be called *once* per packet !!! */
     74 
     75 /* Then you setup per-message nonce and pass the length of the message */
     76 int CRYPTO_ccm128_setiv(CCM128_CONTEXT *ctx,
     77 	const unsigned char *nonce,size_t nlen,size_t mlen)
     78 {
     79 	unsigned int L = ctx->nonce.c[0]&7;	/* the L parameter */
     80 
     81 	if (nlen<(14-L)) return -1;		/* nonce is too short */
     82 
     83 	if (sizeof(mlen)==8 && L>=3) {
     84 		ctx->nonce.c[8]  = (u8)(mlen>>(56%(sizeof(mlen)*8)));
     85 		ctx->nonce.c[9]  = (u8)(mlen>>(48%(sizeof(mlen)*8)));
     86 		ctx->nonce.c[10] = (u8)(mlen>>(40%(sizeof(mlen)*8)));
     87 		ctx->nonce.c[11] = (u8)(mlen>>(32%(sizeof(mlen)*8)));
     88 	}
     89 	else
     90 		*(u32*)(&ctx->nonce.c[8]) = 0;
     91 
     92 	ctx->nonce.c[12] = (u8)(mlen>>24);
     93 	ctx->nonce.c[13] = (u8)(mlen>>16);
     94 	ctx->nonce.c[14] = (u8)(mlen>>8);
     95 	ctx->nonce.c[15] = (u8)mlen;
     96 
     97 	ctx->nonce.c[0] &= ~0x40;	/* clear Adata flag */
     98 	memcpy(&ctx->nonce.c[1],nonce,14-L);
     99 
    100 	return 0;
    101 }
    102 
    103 /* Then you pass additional authentication data, this is optional */
    104 void CRYPTO_ccm128_aad(CCM128_CONTEXT *ctx,
    105 	const unsigned char *aad,size_t alen)
    106 {	unsigned int i;
    107 	block128_f block = ctx->block;
    108 
    109 	if (alen==0) return;
    110 
    111 	ctx->nonce.c[0] |= 0x40;	/* set Adata flag */
    112 	(*block)(ctx->nonce.c,ctx->cmac.c,ctx->key),
    113 	ctx->blocks++;
    114 
    115 	if (alen<(0x10000-0x100)) {
    116 		ctx->cmac.c[0] ^= (u8)(alen>>8);
    117 		ctx->cmac.c[1] ^= (u8)alen;
    118 		i=2;
    119 	}
    120 	else if (sizeof(alen)==8 && alen>=(size_t)1<<(32%(sizeof(alen)*8))) {
    121 		ctx->cmac.c[0] ^= 0xFF;
    122 		ctx->cmac.c[1] ^= 0xFF;
    123 		ctx->cmac.c[2] ^= (u8)(alen>>(56%(sizeof(alen)*8)));
    124 		ctx->cmac.c[3] ^= (u8)(alen>>(48%(sizeof(alen)*8)));
    125 		ctx->cmac.c[4] ^= (u8)(alen>>(40%(sizeof(alen)*8)));
    126 		ctx->cmac.c[5] ^= (u8)(alen>>(32%(sizeof(alen)*8)));
    127 		ctx->cmac.c[6] ^= (u8)(alen>>24);
    128 		ctx->cmac.c[7] ^= (u8)(alen>>16);
    129 		ctx->cmac.c[8] ^= (u8)(alen>>8);
    130 		ctx->cmac.c[9] ^= (u8)alen;
    131 		i=10;
    132 	}
    133 	else {
    134 		ctx->cmac.c[0] ^= 0xFF;
    135 		ctx->cmac.c[1] ^= 0xFE;
    136 		ctx->cmac.c[2] ^= (u8)(alen>>24);
    137 		ctx->cmac.c[3] ^= (u8)(alen>>16);
    138 		ctx->cmac.c[4] ^= (u8)(alen>>8);
    139 		ctx->cmac.c[5] ^= (u8)alen;
    140 		i=6;
    141 	}
    142 
    143 	do {
    144 		for(;i<16 && alen;++i,++aad,--alen)
    145 			ctx->cmac.c[i] ^= *aad;
    146 		(*block)(ctx->cmac.c,ctx->cmac.c,ctx->key),
    147 		ctx->blocks++;
    148 		i=0;
    149 	} while (alen);
    150 }
    151 
    152 /* Finally you encrypt or decrypt the message */
    153 
    154 /* counter part of nonce may not be larger than L*8 bits,
    155  * L is not larger than 8, therefore 64-bit counter... */
    156 static void ctr64_inc(unsigned char *counter) {
    157 	unsigned int n=8;
    158 	u8  c;
    159 
    160 	counter += 8;
    161 	do {
    162 		--n;
    163 		c = counter[n];
    164 		++c;
    165 		counter[n] = c;
    166 		if (c) return;
    167 	} while (n);
    168 }
    169 
    170 int CRYPTO_ccm128_encrypt(CCM128_CONTEXT *ctx,
    171 	const unsigned char *inp, unsigned char *out,
    172 	size_t len)
    173 {
    174 	size_t		n;
    175 	unsigned int	i,L;
    176 	unsigned char	flags0	= ctx->nonce.c[0];
    177 	block128_f	block	= ctx->block;
    178 	void *		key	= ctx->key;
    179 	union { u64 u[2]; u8 c[16]; } scratch;
    180 
    181 	if (!(flags0&0x40))
    182 		(*block)(ctx->nonce.c,ctx->cmac.c,key),
    183 		ctx->blocks++;
    184 
    185 	ctx->nonce.c[0] = L = flags0&7;
    186 	for (n=0,i=15-L;i<15;++i) {
    187 		n |= ctx->nonce.c[i];
    188 		ctx->nonce.c[i]=0;
    189 		n <<= 8;
    190 	}
    191 	n |= ctx->nonce.c[15];	/* reconstructed length */
    192 	ctx->nonce.c[15]=1;
    193 
    194 	if (n!=len) return -1;	/* length mismatch */
    195 
    196 	ctx->blocks += ((len+15)>>3)|1;
    197 	if (ctx->blocks > (U64(1)<<61))	return -2; /* too much data */
    198 
    199 	while (len>=16) {
    200 #if defined(STRICT_ALIGNMENT)
    201 		union { u64 u[2]; u8 c[16]; } temp;
    202 
    203 		memcpy (temp.c,inp,16);
    204 		ctx->cmac.u[0] ^= temp.u[0];
    205 		ctx->cmac.u[1] ^= temp.u[1];
    206 #else
    207 		ctx->cmac.u[0] ^= ((u64*)inp)[0];
    208 		ctx->cmac.u[1] ^= ((u64*)inp)[1];
    209 #endif
    210 		(*block)(ctx->cmac.c,ctx->cmac.c,key);
    211 		(*block)(ctx->nonce.c,scratch.c,key);
    212 		ctr64_inc(ctx->nonce.c);
    213 #if defined(STRICT_ALIGNMENT)
    214 		temp.u[0] ^= scratch.u[0];
    215 		temp.u[1] ^= scratch.u[1];
    216 		memcpy(out,temp.c,16);
    217 #else
    218 		((u64*)out)[0] = scratch.u[0]^((u64*)inp)[0];
    219 		((u64*)out)[1] = scratch.u[1]^((u64*)inp)[1];
    220 #endif
    221 		inp += 16;
    222 		out += 16;
    223 		len -= 16;
    224 	}
    225 
    226 	if (len) {
    227 		for (i=0; i<len; ++i) ctx->cmac.c[i] ^= inp[i];
    228 		(*block)(ctx->cmac.c,ctx->cmac.c,key);
    229 		(*block)(ctx->nonce.c,scratch.c,key);
    230 		for (i=0; i<len; ++i) out[i] = scratch.c[i]^inp[i];
    231 	}
    232 
    233 	for (i=15-L;i<16;++i)
    234 		ctx->nonce.c[i]=0;
    235 
    236 	(*block)(ctx->nonce.c,scratch.c,key);
    237 	ctx->cmac.u[0] ^= scratch.u[0];
    238 	ctx->cmac.u[1] ^= scratch.u[1];
    239 
    240 	ctx->nonce.c[0] = flags0;
    241 
    242 	return 0;
    243 }
    244 
    245 int CRYPTO_ccm128_decrypt(CCM128_CONTEXT *ctx,
    246 	const unsigned char *inp, unsigned char *out,
    247 	size_t len)
    248 {
    249 	size_t		n;
    250 	unsigned int	i,L;
    251 	unsigned char	flags0	= ctx->nonce.c[0];
    252 	block128_f	block	= ctx->block;
    253 	void *		key	= ctx->key;
    254 	union { u64 u[2]; u8 c[16]; } scratch;
    255 
    256 	if (!(flags0&0x40))
    257 		(*block)(ctx->nonce.c,ctx->cmac.c,key);
    258 
    259 	ctx->nonce.c[0] = L = flags0&7;
    260 	for (n=0,i=15-L;i<15;++i) {
    261 		n |= ctx->nonce.c[i];
    262 		ctx->nonce.c[i]=0;
    263 		n <<= 8;
    264 	}
    265 	n |= ctx->nonce.c[15];	/* reconstructed length */
    266 	ctx->nonce.c[15]=1;
    267 
    268 	if (n!=len) return -1;
    269 
    270 	while (len>=16) {
    271 #if defined(STRICT_ALIGNMENT)
    272 		union { u64 u[2]; u8 c[16]; } temp;
    273 #endif
    274 		(*block)(ctx->nonce.c,scratch.c,key);
    275 		ctr64_inc(ctx->nonce.c);
    276 #if defined(STRICT_ALIGNMENT)
    277 		memcpy (temp.c,inp,16);
    278 		ctx->cmac.u[0] ^= (scratch.u[0] ^= temp.u[0]);
    279 		ctx->cmac.u[1] ^= (scratch.u[1] ^= temp.u[1]);
    280 		memcpy (out,scratch.c,16);
    281 #else
    282 		ctx->cmac.u[0] ^= (((u64*)out)[0] = scratch.u[0]^((u64*)inp)[0]);
    283 		ctx->cmac.u[1] ^= (((u64*)out)[1] = scratch.u[1]^((u64*)inp)[1]);
    284 #endif
    285 		(*block)(ctx->cmac.c,ctx->cmac.c,key);
    286 
    287 		inp += 16;
    288 		out += 16;
    289 		len -= 16;
    290 	}
    291 
    292 	if (len) {
    293 		(*block)(ctx->nonce.c,scratch.c,key);
    294 		for (i=0; i<len; ++i)
    295 			ctx->cmac.c[i] ^= (out[i] = scratch.c[i]^inp[i]);
    296 		(*block)(ctx->cmac.c,ctx->cmac.c,key);
    297 	}
    298 
    299 	for (i=15-L;i<16;++i)
    300 		ctx->nonce.c[i]=0;
    301 
    302 	(*block)(ctx->nonce.c,scratch.c,key);
    303 	ctx->cmac.u[0] ^= scratch.u[0];
    304 	ctx->cmac.u[1] ^= scratch.u[1];
    305 
    306 	ctx->nonce.c[0] = flags0;
    307 
    308 	return 0;
    309 }
    310 
    311 static void ctr64_add (unsigned char *counter,size_t inc)
    312 {	size_t n=8, val=0;
    313 
    314 	counter += 8;
    315 	do {
    316 		--n;
    317 		val += counter[n] + (inc&0xff);
    318 		counter[n] = (unsigned char)val;
    319 		val >>= 8;	/* carry bit */
    320 		inc >>= 8;
    321 	} while(n && (inc || val));
    322 }
    323 
    324 int CRYPTO_ccm128_encrypt_ccm64(CCM128_CONTEXT *ctx,
    325 	const unsigned char *inp, unsigned char *out,
    326 	size_t len,ccm128_f stream)
    327 {
    328 	size_t		n;
    329 	unsigned int	i,L;
    330 	unsigned char	flags0	= ctx->nonce.c[0];
    331 	block128_f	block	= ctx->block;
    332 	void *		key	= ctx->key;
    333 	union { u64 u[2]; u8 c[16]; } scratch;
    334 
    335 	if (!(flags0&0x40))
    336 		(*block)(ctx->nonce.c,ctx->cmac.c,key),
    337 		ctx->blocks++;
    338 
    339 	ctx->nonce.c[0] = L = flags0&7;
    340 	for (n=0,i=15-L;i<15;++i) {
    341 		n |= ctx->nonce.c[i];
    342 		ctx->nonce.c[i]=0;
    343 		n <<= 8;
    344 	}
    345 	n |= ctx->nonce.c[15];	/* reconstructed length */
    346 	ctx->nonce.c[15]=1;
    347 
    348 	if (n!=len) return -1;	/* length mismatch */
    349 
    350 	ctx->blocks += ((len+15)>>3)|1;
    351 	if (ctx->blocks > (U64(1)<<61))	return -2; /* too much data */
    352 
    353 	if ((n=len/16)) {
    354 		(*stream)(inp,out,n,key,ctx->nonce.c,ctx->cmac.c);
    355 		n   *= 16;
    356 		inp += n;
    357 		out += n;
    358 		len -= n;
    359 		if (len) ctr64_add(ctx->nonce.c,n/16);
    360 	}
    361 
    362 	if (len) {
    363 		for (i=0; i<len; ++i) ctx->cmac.c[i] ^= inp[i];
    364 		(*block)(ctx->cmac.c,ctx->cmac.c,key);
    365 		(*block)(ctx->nonce.c,scratch.c,key);
    366 		for (i=0; i<len; ++i) out[i] = scratch.c[i]^inp[i];
    367 	}
    368 
    369 	for (i=15-L;i<16;++i)
    370 		ctx->nonce.c[i]=0;
    371 
    372 	(*block)(ctx->nonce.c,scratch.c,key);
    373 	ctx->cmac.u[0] ^= scratch.u[0];
    374 	ctx->cmac.u[1] ^= scratch.u[1];
    375 
    376 	ctx->nonce.c[0] = flags0;
    377 
    378 	return 0;
    379 }
    380 
    381 int CRYPTO_ccm128_decrypt_ccm64(CCM128_CONTEXT *ctx,
    382 	const unsigned char *inp, unsigned char *out,
    383 	size_t len,ccm128_f stream)
    384 {
    385 	size_t		n;
    386 	unsigned int	i,L;
    387 	unsigned char	flags0	= ctx->nonce.c[0];
    388 	block128_f	block	= ctx->block;
    389 	void *		key	= ctx->key;
    390 	union { u64 u[2]; u8 c[16]; } scratch;
    391 
    392 	if (!(flags0&0x40))
    393 		(*block)(ctx->nonce.c,ctx->cmac.c,key);
    394 
    395 	ctx->nonce.c[0] = L = flags0&7;
    396 	for (n=0,i=15-L;i<15;++i) {
    397 		n |= ctx->nonce.c[i];
    398 		ctx->nonce.c[i]=0;
    399 		n <<= 8;
    400 	}
    401 	n |= ctx->nonce.c[15];	/* reconstructed length */
    402 	ctx->nonce.c[15]=1;
    403 
    404 	if (n!=len) return -1;
    405 
    406 	if ((n=len/16)) {
    407 		(*stream)(inp,out,n,key,ctx->nonce.c,ctx->cmac.c);
    408 		n   *= 16;
    409 		inp += n;
    410 		out += n;
    411 		len -= n;
    412 		if (len) ctr64_add(ctx->nonce.c,n/16);
    413 	}
    414 
    415 	if (len) {
    416 		(*block)(ctx->nonce.c,scratch.c,key);
    417 		for (i=0; i<len; ++i)
    418 			ctx->cmac.c[i] ^= (out[i] = scratch.c[i]^inp[i]);
    419 		(*block)(ctx->cmac.c,ctx->cmac.c,key);
    420 	}
    421 
    422 	for (i=15-L;i<16;++i)
    423 		ctx->nonce.c[i]=0;
    424 
    425 	(*block)(ctx->nonce.c,scratch.c,key);
    426 	ctx->cmac.u[0] ^= scratch.u[0];
    427 	ctx->cmac.u[1] ^= scratch.u[1];
    428 
    429 	ctx->nonce.c[0] = flags0;
    430 
    431 	return 0;
    432 }
    433 
    434 size_t CRYPTO_ccm128_tag(CCM128_CONTEXT *ctx,unsigned char *tag,size_t len)
    435 {	unsigned int M = (ctx->nonce.c[0]>>3)&7;	/* the M parameter */
    436 
    437 	M *= 2; M += 2;
    438 	if (len<M)	return 0;
    439 	memcpy(tag,ctx->cmac.c,M);
    440 	return M;
    441 }
    442