X-Git-Url: https://git.openssl.org/gitweb/?a=blobdiff_plain;f=crypto%2Fmodes%2Fccm128.c;h=3ce11d0d984cbcd34ea507e279677e775065843e;hb=79c6c4e828834c4b979940eb537f8a2b4b103376;hp=ced0a2b5d73bb247b6b370b3e22ab8353889de6a;hpb=632d83f0a3fbda2e7f4e556183792597b7db88fc;p=openssl.git diff --git a/crypto/modes/ccm128.c b/crypto/modes/ccm128.c index ced0a2b5d7..3ce11d0d98 100644 --- a/crypto/modes/ccm128.c +++ b/crypto/modes/ccm128.c @@ -58,15 +58,8 @@ #endif #include -typedef struct { - union { u8 c[16]; size_t s[16/sizeof(size_t)]; } nonce, cmac, - scratch, inp; - u64 blocks; - block128_f block; - void *key; -} CCM128_CONTEXT; - -/* First you setup M and L parameters and pass the key schedule */ +/* First you setup M and L parameters and pass the key schedule. + * This is called once per session setup... */ void CRYPTO_ccm128_init(CCM128_CONTEXT *ctx, unsigned int M,unsigned int L,void *key,block128_f block) { @@ -94,7 +87,7 @@ int CRYPTO_ccm128_setiv(CCM128_CONTEXT *ctx, ctx->nonce.c[11] = (u8)(mlen>>(32%(sizeof(mlen)*8))); } else - *((size_t *)&ctx->nonce.s[8]) = 0; + ctx->nonce.u[1] = 0; ctx->nonce.c[12] = (u8)(mlen>>24); ctx->nonce.c[13] = (u8)(mlen>>16); @@ -111,11 +104,12 @@ int CRYPTO_ccm128_setiv(CCM128_CONTEXT *ctx, void CRYPTO_ccm128_aad(CCM128_CONTEXT *ctx, const unsigned char *aad,size_t alen) { unsigned int i; + block128_f block = ctx->block; if (alen==0) return; ctx->nonce.c[0] |= 0x40; /* set Adata flag */ - (*ctx->block)(ctx->nonce.c,ctx->cmac.c,ctx->key), + (*block)(ctx->nonce.c,ctx->cmac.c,ctx->key), ctx->blocks++; if (alen<(0x10000-0x100)) { @@ -123,7 +117,7 @@ void CRYPTO_ccm128_aad(CCM128_CONTEXT *ctx, ctx->cmac.c[1] ^= (u8)alen; i=2; } - else if (sizeof(alen)==8 && alen>=(size_t)1<<32) { + else if (sizeof(alen)==8 && alen>=(size_t)1<<(32%(sizeof(alen)*8))) { ctx->cmac.c[0] ^= 0xFF; ctx->cmac.c[1] ^= 0xFF; ctx->cmac.c[2] ^= (u8)(alen>>(56%(sizeof(alen)*8))); @@ -149,7 +143,7 @@ void CRYPTO_ccm128_aad(CCM128_CONTEXT *ctx, do { for(;i<16 && alen;++i,++aad,--alen) ctx->cmac.c[i] ^= *aad; - (*ctx->block)(ctx->cmac.c,ctx->cmac.c,ctx->key), + (*block)(ctx->cmac.c,ctx->cmac.c,ctx->key), ctx->blocks++; i=0; } while (alen); @@ -157,10 +151,13 @@ void CRYPTO_ccm128_aad(CCM128_CONTEXT *ctx, /* Finally you encrypt or decrypt the message */ -static void ctr128_inc(unsigned char *counter) { - unsigned int n=16; +/* counter part of nonce may not be larger than L*8 bits, + * L is not larger than 8, therefore 64-bit counter... */ +static void ctr64_inc(unsigned char *counter) { + unsigned int n=8; u8 c; + counter += 8; do { --n; c = counter[n]; @@ -175,16 +172,20 @@ int CRYPTO_ccm128_encrypt(CCM128_CONTEXT *ctx, size_t len) { size_t n; - unsigned int i; - unsigned char flags = ctx->nonce.c[0]; - - if (!(flags&0x40)) - (*ctx->block)(ctx->nonce.c,ctx->cmac.c,ctx->key), + unsigned int i,L; + unsigned char flags0 = ctx->nonce.c[0]; + block128_f block = ctx->block; + void * key = ctx->key; + union { u64 u[2]; u8 c[16]; } scratch; + + if (!(flags0&0x40)) + (*block)(ctx->nonce.c,ctx->cmac.c,key), ctx->blocks++; - flags &= 7; /* extract the L parameter */ - for (n=0,i=15-flags;i<15;++i) { - n |= ctx->nonce.c[i]; ctx->nonce.c[i]=0; + ctx->nonce.c[0] = L = flags0&7; + for (n=0,i=15-L;i<15;++i) { + n |= ctx->nonce.c[i]; + ctx->nonce.c[i]=0; n <<= 8; } n |= ctx->nonce.c[15]; /* reconstructed length */ @@ -197,23 +198,25 @@ int CRYPTO_ccm128_encrypt(CCM128_CONTEXT *ctx, while (len>=16) { #if defined(STRICT_ALIGNMENT) - memcpy (ctx->inp.c,inp,16); - for (i=0; i<16/sizeof(size_t); ++i) - ctx->cmac.s[i] ^= ctx->inp.s[i]; + union { u64 u[2]; u8 c[16]; } temp; + + memcpy (temp.c,inp,16); + ctx->cmac.u[0] ^= temp.u[0]; + ctx->cmac.u[1] ^= temp.u[1]; #else - for (i=0; i<16/sizeof(size_t); ++i) - ctx->cmac.s[i] ^= ((size_t*)inp)[i]; + ctx->cmac.u[0] ^= ((u64*)inp)[0]; + ctx->cmac.u[1] ^= ((u64*)inp)[1]; #endif - (*ctx->block)(ctx->cmac.c,ctx->cmac.c,ctx->key); - (*ctx->block)(ctx->nonce.c,ctx->scratch.c,ctx->key); - ctr128_inc(ctx->nonce.c); + (*block)(ctx->cmac.c,ctx->cmac.c,key); + (*block)(ctx->nonce.c,scratch.c,key); + ctr64_inc(ctx->nonce.c); #if defined(STRICT_ALIGNMENT) - for (i=0; i<16/sizeof(size_t); ++i) - ctx->inp.s[i] ^= ctx->scratch.s[i]; - memcpy(out,ctx->inp.c,16); + temp.u[0] ^= scratch.u[0]; + temp.u[1] ^= scratch.u[1]; + memcpy(out,temp.c,16); #else - for (i=0; i<16/sizeof(size_t); ++i) - ((size_t*)out)[i] = ctx->scratch.s[i]^((size_t*)inp)[i]; + ((u64*)out)[0] = scratch.u[0]^((u64*)inp)[0]; + ((u64*)out)[1] = scratch.u[1]^((u64*)inp)[1]; #endif inp += 16; out += 16; @@ -222,17 +225,19 @@ int CRYPTO_ccm128_encrypt(CCM128_CONTEXT *ctx, if (len) { for (i=0; icmac.c[i] ^= inp[i]; - (*ctx->block)(ctx->cmac.c,ctx->cmac.c,ctx->key); - (*ctx->block)(ctx->nonce.c,ctx->scratch.c,ctx->key); - for (i=0; iscratch.c[i]^inp[i]; + (*block)(ctx->cmac.c,ctx->cmac.c,key); + (*block)(ctx->nonce.c,scratch.c,key); + for (i=0; inonce.c[i]=0; - (*ctx->block)(ctx->nonce.c,ctx->scratch.c,ctx->key); - for (i=0; i<16/sizeof(size_t); ++i) - ctx->cmac.s[i] ^= ctx->scratch.s[i]; + (*block)(ctx->nonce.c,scratch.c,key); + ctx->cmac.u[0] ^= scratch.u[0]; + ctx->cmac.u[1] ^= scratch.u[1]; + + ctx->nonce.c[0] = flags0; return 0; } @@ -242,15 +247,19 @@ int CRYPTO_ccm128_decrypt(CCM128_CONTEXT *ctx, size_t len) { size_t n; - unsigned int i; - unsigned char flags = ctx->nonce.c[0]; - - if (!(flags&0x40)) - (*ctx->block)(ctx->nonce.c,ctx->cmac.c,ctx->key); - - flags &= 7; /* extract the L parameter */ - for (n=0,i=15-flags;i<15;++i) { - n |= ctx->nonce.c[i]; ctx->nonce.c[i]=0; + unsigned int i,L; + unsigned char flags0 = ctx->nonce.c[0]; + block128_f block = ctx->block; + void * key = ctx->key; + union { u64 u[2]; u8 c[16]; } scratch; + + if (!(flags0&0x40)) + (*block)(ctx->nonce.c,ctx->cmac.c,key); + + ctx->nonce.c[0] = L = flags0&7; + for (n=0,i=15-L;i<15;++i) { + n |= ctx->nonce.c[i]; + ctx->nonce.c[i]=0; n <<= 8; } n |= ctx->nonce.c[15]; /* reconstructed length */ @@ -259,18 +268,21 @@ int CRYPTO_ccm128_decrypt(CCM128_CONTEXT *ctx, if (n!=len) return -1; while (len>=16) { - (*ctx->block)(ctx->nonce.c,ctx->scratch.c,ctx->key); - ctr128_inc(ctx->nonce.c); #if defined(STRICT_ALIGNMENT) - memcpy (ctx->inp.c,inp,16); - for (i=0; i<16/sizeof(size_t); ++i) - ctx->cmac.s[i] ^= (ctx->scratch.s[i] ^= ctx->inp.s[i]); - memcpy (out,ctx->scratch,16); + union { u64 u[2]; u8 c[16]; } temp; +#endif + (*block)(ctx->nonce.c,scratch.c,key); + ctr64_inc(ctx->nonce.c); +#if defined(STRICT_ALIGNMENT) + memcpy (temp.c,inp,16); + ctx->cmac.u[0] ^= (scratch.u[0] ^= temp.u[0]); + ctx->cmac.u[1] ^= (scratch.u[1] ^= temp.u[1]); + memcpy (out,scratch.c,16); #else - for (i=0; i<16/sizeof(size_t); ++i) - ctx->cmac.s[i] ^= ((size_t*)out)[i] = ctx->scratch.s[i]^((size_t*)inp)[i]; + ctx->cmac.u[0] ^= (((u64*)out)[0] = scratch.u[0]^((u64*)inp)[0]); + ctx->cmac.u[1] ^= (((u64*)out)[1] = scratch.u[1]^((u64*)inp)[1]); #endif - (*ctx->block)(ctx->cmac.c,ctx->cmac.c,ctx->key); + (*block)(ctx->cmac.c,ctx->cmac.c,key); inp += 16; out += 16; @@ -278,18 +290,143 @@ int CRYPTO_ccm128_decrypt(CCM128_CONTEXT *ctx, } if (len) { - (*ctx->block)(ctx->nonce.c,ctx->scratch.c,ctx->key); - for (i=0; icmac.c[i] ^= (out[i] = ctx->scratch.c[i]^inp[i]); - (*ctx->block)(ctx->cmac.c,ctx->cmac.c,ctx->key); + (*block)(ctx->nonce.c,scratch.c,key); + for (i=0; icmac.c[i] ^= (out[i] = scratch.c[i]^inp[i]); + (*block)(ctx->cmac.c,ctx->cmac.c,key); } - for (i=15-flags;i<16;++i) + for (i=15-L;i<16;++i) + ctx->nonce.c[i]=0; + + (*block)(ctx->nonce.c,scratch.c,key); + ctx->cmac.u[0] ^= scratch.u[0]; + ctx->cmac.u[1] ^= scratch.u[1]; + + ctx->nonce.c[0] = flags0; + + return 0; +} + +static void ctr64_add (unsigned char *counter,size_t inc) +{ size_t n=8, val=0; + + counter += 8; + do { + --n; + val += counter[n] + (inc&0xff); + counter[n] = (unsigned char)val; + val >>= 8; /* carry bit */ + inc >>= 8; + } while(n && (inc || val)); +} + +int CRYPTO_ccm128_encrypt_ccm64(CCM128_CONTEXT *ctx, + const unsigned char *inp, unsigned char *out, + size_t len,ccm128_f stream) +{ + size_t n; + unsigned int i,L; + unsigned char flags0 = ctx->nonce.c[0]; + block128_f block = ctx->block; + void * key = ctx->key; + union { u64 u[2]; u8 c[16]; } scratch; + + if (!(flags0&0x40)) + (*block)(ctx->nonce.c,ctx->cmac.c,key), + ctx->blocks++; + + ctx->nonce.c[0] = L = flags0&7; + for (n=0,i=15-L;i<15;++i) { + n |= ctx->nonce.c[i]; ctx->nonce.c[i]=0; + n <<= 8; + } + n |= ctx->nonce.c[15]; /* reconstructed length */ + ctx->nonce.c[15]=1; + + if (n!=len) return -1; /* length mismatch */ + + ctx->blocks += ((len+15)>>3)|1; + if (ctx->blocks > (U64(1)<<61)) return -2; /* too much data */ + + if ((n=len/16)) { + (*stream)(inp,out,n,key,ctx->nonce.c,ctx->cmac.c); + n *= 16; + inp += n; + out += n; + len -= n; + if (len) ctr64_add(ctx->nonce.c,n/16); + } + + if (len) { + for (i=0; icmac.c[i] ^= inp[i]; + (*block)(ctx->cmac.c,ctx->cmac.c,key); + (*block)(ctx->nonce.c,scratch.c,key); + for (i=0; inonce.c[i]=0; + + (*block)(ctx->nonce.c,scratch.c,key); + ctx->cmac.u[0] ^= scratch.u[0]; + ctx->cmac.u[1] ^= scratch.u[1]; + + ctx->nonce.c[0] = flags0; + + return 0; +} + +int CRYPTO_ccm128_decrypt_ccm64(CCM128_CONTEXT *ctx, + const unsigned char *inp, unsigned char *out, + size_t len,ccm128_f stream) +{ + size_t n; + unsigned int i,L; + unsigned char flags0 = ctx->nonce.c[0]; + block128_f block = ctx->block; + void * key = ctx->key; + union { u64 u[2]; u8 c[16]; } scratch; + + if (!(flags0&0x40)) + (*block)(ctx->nonce.c,ctx->cmac.c,key); + + ctx->nonce.c[0] = L = flags0&7; + for (n=0,i=15-L;i<15;++i) { + n |= ctx->nonce.c[i]; + ctx->nonce.c[i]=0; + n <<= 8; + } + n |= ctx->nonce.c[15]; /* reconstructed length */ + ctx->nonce.c[15]=1; + + if (n!=len) return -1; + + if ((n=len/16)) { + (*stream)(inp,out,n,key,ctx->nonce.c,ctx->cmac.c); + n *= 16; + inp += n; + out += n; + len -= n; + if (len) ctr64_add(ctx->nonce.c,n/16); + } + + if (len) { + (*block)(ctx->nonce.c,scratch.c,key); + for (i=0; icmac.c[i] ^= (out[i] = scratch.c[i]^inp[i]); + (*block)(ctx->cmac.c,ctx->cmac.c,key); + } + + for (i=15-L;i<16;++i) + ctx->nonce.c[i]=0; + + (*block)(ctx->nonce.c,scratch.c,key); + ctx->cmac.u[0] ^= scratch.u[0]; + ctx->cmac.u[1] ^= scratch.u[1]; - (*ctx->block)(ctx->nonce.c,ctx->scratch.c,ctx->key); - for (i=0; i<16/sizeof(size_t); ++i) - ctx->cmac.s[i] ^= ctx->scratch.s[i]; + ctx->nonce.c[0] = flags0; return 0; }