12c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org/* ==================================================================== 22c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * Copyright (c) 2011 The OpenSSL Project. All rights reserved. 32c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 42c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * Redistribution and use in source and binary forms, with or without 52c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * modification, are permitted provided that the following conditions 62c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * are met: 72c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 82c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 1. Redistributions of source code must retain the above copyright 92c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * notice, this list of conditions and the following disclaimer. 102c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 112c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 2. Redistributions in binary form must reproduce the above copyright 122c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * notice, this list of conditions and the following disclaimer in 132c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * the documentation and/or other materials provided with the 142c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * distribution. 152c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 162c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 3. All advertising materials mentioning features or use of this 172c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * software must display the following acknowledgment: 182c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * "This product includes software developed by the OpenSSL Project 192c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 202c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 212c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 222c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * endorse or promote products derived from this software without 232c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * prior written permission. For written permission, please contact 242c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * openssl-core@openssl.org. 252c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 262c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 5. Products derived from this software may not be called "OpenSSL" 272c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * nor may "OpenSSL" appear in their names without prior written 282c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * permission of the OpenSSL Project. 292c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 302c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 6. Redistributions of any form whatsoever must retain the following 312c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * acknowledgment: 322c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * "This product includes software developed by the OpenSSL Project 332c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 342c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * 352c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 362c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 372c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 382c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 392c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 402c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 412c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 422c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 432c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 442c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 452c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 462c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * OF THE POSSIBILITY OF SUCH DAMAGE. 472c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * ==================================================================== 482c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org */ 492c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 502c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#include <openssl/crypto.h> 512c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#include "modes_lcl.h" 522c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#include <string.h> 532c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 542c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#ifndef MODES_DEBUG 552c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org# ifndef NDEBUG 562c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org# define NDEBUG 572c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org# endif 582c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif 592c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#include <assert.h> 602c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 612c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org/* First you setup M and L parameters and pass the key schedule. 622c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * This is called once per session setup... */ 632c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgvoid CRYPTO_ccm128_init(CCM128_CONTEXT *ctx, 642c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org unsigned int M,unsigned int L,void *key,block128_f block) 652c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org{ 662c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org memset(ctx->nonce.c,0,sizeof(ctx->nonce.c)); 672c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[0] = ((u8)(L-1)&7) | (u8)(((M-2)/2)&7)<<3; 682c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->blocks = 0; 692c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->block = block; 702c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->key = key; 712c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org} 722c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 732c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org/* !!! Following interfaces are to be called *once* per packet !!! */ 742c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 752c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org/* Then you setup per-message nonce and pass the length of the message */ 762c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgint CRYPTO_ccm128_setiv(CCM128_CONTEXT *ctx, 772c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org const unsigned char *nonce,size_t nlen,size_t mlen) 782c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org{ 792c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org unsigned int L = ctx->nonce.c[0]&7; /* the L parameter */ 802c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 812c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (nlen<(14-L)) return -1; /* nonce is too short */ 822c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 832c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (sizeof(mlen)==8 && L>=3) { 842c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[8] = (u8)(mlen>>(56%(sizeof(mlen)*8))); 852c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[9] = (u8)(mlen>>(48%(sizeof(mlen)*8))); 862c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[10] = (u8)(mlen>>(40%(sizeof(mlen)*8))); 872c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[11] = (u8)(mlen>>(32%(sizeof(mlen)*8))); 882c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 892c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org else 902c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org *(u32*)(&ctx->nonce.c[8]) = 0; 912c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 922c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[12] = (u8)(mlen>>24); 932c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[13] = (u8)(mlen>>16); 942c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[14] = (u8)(mlen>>8); 952c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[15] = (u8)mlen; 962c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 972c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[0] &= ~0x40; /* clear Adata flag */ 982c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org memcpy(&ctx->nonce.c[1],nonce,14-L); 992c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1002c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org return 0; 1012c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org} 1022c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1032c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org/* Then you pass additional authentication data, this is optional */ 1042c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgvoid CRYPTO_ccm128_aad(CCM128_CONTEXT *ctx, 1052c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org const unsigned char *aad,size_t alen) 1062c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org{ unsigned int i; 1072c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org block128_f block = ctx->block; 1082c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1092c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (alen==0) return; 1102c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1112c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[0] |= 0x40; /* set Adata flag */ 1122c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (*block)(ctx->nonce.c,ctx->cmac.c,ctx->key), 1132c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->blocks++; 1142c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1152c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (alen<(0x10000-0x100)) { 1162c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.c[0] ^= (u8)(alen>>8); 1172c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.c[1] ^= (u8)alen; 1182c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org i=2; 1192c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 1202c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org else if (sizeof(alen)==8 && alen>=(size_t)1<<(32%(sizeof(alen)*8))) { 1212c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.c[0] ^= 0xFF; 1222c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.c[1] ^= 0xFF; 1232c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.c[2] ^= (u8)(alen>>(56%(sizeof(alen)*8))); 1242c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.c[3] ^= (u8)(alen>>(48%(sizeof(alen)*8))); 1252c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.c[4] ^= (u8)(alen>>(40%(sizeof(alen)*8))); 1262c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.c[5] ^= (u8)(alen>>(32%(sizeof(alen)*8))); 1272c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.c[6] ^= (u8)(alen>>24); 1282c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.c[7] ^= (u8)(alen>>16); 1292c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.c[8] ^= (u8)(alen>>8); 1302c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.c[9] ^= (u8)alen; 1312c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org i=10; 1322c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 1332c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org else { 1342c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.c[0] ^= 0xFF; 1352c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.c[1] ^= 0xFE; 1362c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.c[2] ^= (u8)(alen>>24); 1372c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.c[3] ^= (u8)(alen>>16); 1382c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.c[4] ^= (u8)(alen>>8); 1392c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.c[5] ^= (u8)alen; 1402c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org i=6; 1412c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 1422c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1432c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org do { 1442c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org for(;i<16 && alen;++i,++aad,--alen) 1452c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.c[i] ^= *aad; 1462c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (*block)(ctx->cmac.c,ctx->cmac.c,ctx->key), 1472c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->blocks++; 1482c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org i=0; 1492c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } while (alen); 1502c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org} 1512c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1522c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org/* Finally you encrypt or decrypt the message */ 1532c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1542c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org/* counter part of nonce may not be larger than L*8 bits, 1552c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org * L is not larger than 8, therefore 64-bit counter... */ 1562c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgstatic void ctr64_inc(unsigned char *counter) { 1572c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org unsigned int n=8; 1582c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org u8 c; 1592c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1602c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org counter += 8; 1612c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org do { 1622c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org --n; 1632c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org c = counter[n]; 1642c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ++c; 1652c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org counter[n] = c; 1662c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (c) return; 1672c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } while (n); 1682c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org} 1692c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1702c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgint CRYPTO_ccm128_encrypt(CCM128_CONTEXT *ctx, 1712c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org const unsigned char *inp, unsigned char *out, 1722c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org size_t len) 1732c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org{ 1742c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org size_t n; 1752c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org unsigned int i,L; 1762c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org unsigned char flags0 = ctx->nonce.c[0]; 1772c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org block128_f block = ctx->block; 1782c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org void * key = ctx->key; 1792c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org union { u64 u[2]; u8 c[16]; } scratch; 1802c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1812c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (!(flags0&0x40)) 1822c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (*block)(ctx->nonce.c,ctx->cmac.c,key), 1832c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->blocks++; 1842c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1852c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[0] = L = flags0&7; 1862c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org for (n=0,i=15-L;i<15;++i) { 1872c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org n |= ctx->nonce.c[i]; 1882c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[i]=0; 1892c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org n <<= 8; 1902c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 1912c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org n |= ctx->nonce.c[15]; /* reconstructed length */ 1922c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[15]=1; 1932c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1942c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (n!=len) return -1; /* length mismatch */ 1952c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1962c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->blocks += ((len+15)>>3)|1; 1972c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (ctx->blocks > (U64(1)<<61)) return -2; /* too much data */ 1982c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 1992c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org while (len>=16) { 2002c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#if defined(STRICT_ALIGNMENT) 2012c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org union { u64 u[2]; u8 c[16]; } temp; 2022c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2032c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org memcpy (temp.c,inp,16); 2042c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.u[0] ^= temp.u[0]; 2052c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.u[1] ^= temp.u[1]; 2062c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#else 2072c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.u[0] ^= ((u64*)inp)[0]; 2082c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.u[1] ^= ((u64*)inp)[1]; 2092c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif 2102c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (*block)(ctx->cmac.c,ctx->cmac.c,key); 2112c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (*block)(ctx->nonce.c,scratch.c,key); 2122c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctr64_inc(ctx->nonce.c); 2132c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#if defined(STRICT_ALIGNMENT) 2142c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org temp.u[0] ^= scratch.u[0]; 2152c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org temp.u[1] ^= scratch.u[1]; 2162c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org memcpy(out,temp.c,16); 2172c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#else 2182c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ((u64*)out)[0] = scratch.u[0]^((u64*)inp)[0]; 2192c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ((u64*)out)[1] = scratch.u[1]^((u64*)inp)[1]; 2202c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif 2212c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org inp += 16; 2222c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org out += 16; 2232c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org len -= 16; 2242c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 2252c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2262c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (len) { 2272c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org for (i=0; i<len; ++i) ctx->cmac.c[i] ^= inp[i]; 2282c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (*block)(ctx->cmac.c,ctx->cmac.c,key); 2292c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (*block)(ctx->nonce.c,scratch.c,key); 2302c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org for (i=0; i<len; ++i) out[i] = scratch.c[i]^inp[i]; 2312c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 2322c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2332c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org for (i=15-L;i<16;++i) 2342c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[i]=0; 2352c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2362c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (*block)(ctx->nonce.c,scratch.c,key); 2372c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.u[0] ^= scratch.u[0]; 2382c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.u[1] ^= scratch.u[1]; 2392c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2402c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[0] = flags0; 2412c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2422c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org return 0; 2432c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org} 2442c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2452c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgint CRYPTO_ccm128_decrypt(CCM128_CONTEXT *ctx, 2462c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org const unsigned char *inp, unsigned char *out, 2472c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org size_t len) 2482c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org{ 2492c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org size_t n; 2502c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org unsigned int i,L; 2512c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org unsigned char flags0 = ctx->nonce.c[0]; 2522c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org block128_f block = ctx->block; 2532c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org void * key = ctx->key; 2542c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org union { u64 u[2]; u8 c[16]; } scratch; 2552c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2562c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (!(flags0&0x40)) 2572c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (*block)(ctx->nonce.c,ctx->cmac.c,key); 2582c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2592c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[0] = L = flags0&7; 2602c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org for (n=0,i=15-L;i<15;++i) { 2612c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org n |= ctx->nonce.c[i]; 2622c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[i]=0; 2632c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org n <<= 8; 2642c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 2652c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org n |= ctx->nonce.c[15]; /* reconstructed length */ 2662c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[15]=1; 2672c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2682c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (n!=len) return -1; 2692c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2702c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org while (len>=16) { 2712c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#if defined(STRICT_ALIGNMENT) 2722c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org union { u64 u[2]; u8 c[16]; } temp; 2732c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif 2742c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (*block)(ctx->nonce.c,scratch.c,key); 2752c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctr64_inc(ctx->nonce.c); 2762c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#if defined(STRICT_ALIGNMENT) 2772c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org memcpy (temp.c,inp,16); 2782c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.u[0] ^= (scratch.u[0] ^= temp.u[0]); 2792c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.u[1] ^= (scratch.u[1] ^= temp.u[1]); 2802c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org memcpy (out,scratch.c,16); 2812c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#else 2822c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.u[0] ^= (((u64*)out)[0] = scratch.u[0]^((u64*)inp)[0]); 2832c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.u[1] ^= (((u64*)out)[1] = scratch.u[1]^((u64*)inp)[1]); 2842c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org#endif 2852c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (*block)(ctx->cmac.c,ctx->cmac.c,key); 2862c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2872c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org inp += 16; 2882c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org out += 16; 2892c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org len -= 16; 2902c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 2912c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2922c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (len) { 2932c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (*block)(ctx->nonce.c,scratch.c,key); 2942c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org for (i=0; i<len; ++i) 2952c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.c[i] ^= (out[i] = scratch.c[i]^inp[i]); 2962c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (*block)(ctx->cmac.c,ctx->cmac.c,key); 2972c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 2982c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 2992c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org for (i=15-L;i<16;++i) 3002c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[i]=0; 3012c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 3022c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (*block)(ctx->nonce.c,scratch.c,key); 3032c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.u[0] ^= scratch.u[0]; 3042c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.u[1] ^= scratch.u[1]; 3052c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 3062c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[0] = flags0; 3072c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 3082c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org return 0; 3092c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org} 3102c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 3112c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgstatic void ctr64_add (unsigned char *counter,size_t inc) 3122c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org{ size_t n=8, val=0; 3132c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 3142c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org counter += 8; 3152c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org do { 3162c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org --n; 3172c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org val += counter[n] + (inc&0xff); 3182c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org counter[n] = (unsigned char)val; 3192c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org val >>= 8; /* carry bit */ 3202c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org inc >>= 8; 3212c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } while(n && (inc || val)); 3222c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org} 3232c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 3242c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgint CRYPTO_ccm128_encrypt_ccm64(CCM128_CONTEXT *ctx, 3252c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org const unsigned char *inp, unsigned char *out, 3262c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org size_t len,ccm128_f stream) 3272c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org{ 3282c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org size_t n; 3292c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org unsigned int i,L; 3302c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org unsigned char flags0 = ctx->nonce.c[0]; 3312c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org block128_f block = ctx->block; 3322c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org void * key = ctx->key; 3332c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org union { u64 u[2]; u8 c[16]; } scratch; 3342c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 3352c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (!(flags0&0x40)) 3362c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (*block)(ctx->nonce.c,ctx->cmac.c,key), 3372c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->blocks++; 3382c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 3392c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[0] = L = flags0&7; 3402c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org for (n=0,i=15-L;i<15;++i) { 3412c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org n |= ctx->nonce.c[i]; 3422c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[i]=0; 3432c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org n <<= 8; 3442c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 3452c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org n |= ctx->nonce.c[15]; /* reconstructed length */ 3462c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[15]=1; 3472c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 3482c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (n!=len) return -1; /* length mismatch */ 3492c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 3502c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->blocks += ((len+15)>>3)|1; 3512c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (ctx->blocks > (U64(1)<<61)) return -2; /* too much data */ 3522c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 3532c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if ((n=len/16)) { 3542c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (*stream)(inp,out,n,key,ctx->nonce.c,ctx->cmac.c); 3552c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org n *= 16; 3562c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org inp += n; 3572c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org out += n; 3582c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org len -= n; 3592c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (len) ctr64_add(ctx->nonce.c,n/16); 3602c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 3612c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 3622c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (len) { 3632c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org for (i=0; i<len; ++i) ctx->cmac.c[i] ^= inp[i]; 3642c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (*block)(ctx->cmac.c,ctx->cmac.c,key); 3652c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (*block)(ctx->nonce.c,scratch.c,key); 3662c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org for (i=0; i<len; ++i) out[i] = scratch.c[i]^inp[i]; 3672c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 3682c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 3692c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org for (i=15-L;i<16;++i) 3702c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[i]=0; 3712c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 3722c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (*block)(ctx->nonce.c,scratch.c,key); 3732c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.u[0] ^= scratch.u[0]; 3742c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.u[1] ^= scratch.u[1]; 3752c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 3762c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[0] = flags0; 3772c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 3782c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org return 0; 3792c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org} 3802c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 3812c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgint CRYPTO_ccm128_decrypt_ccm64(CCM128_CONTEXT *ctx, 3822c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org const unsigned char *inp, unsigned char *out, 3832c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org size_t len,ccm128_f stream) 3842c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org{ 3852c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org size_t n; 3862c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org unsigned int i,L; 3872c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org unsigned char flags0 = ctx->nonce.c[0]; 3882c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org block128_f block = ctx->block; 3892c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org void * key = ctx->key; 3902c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org union { u64 u[2]; u8 c[16]; } scratch; 3912c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 3922c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (!(flags0&0x40)) 3932c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (*block)(ctx->nonce.c,ctx->cmac.c,key); 3942c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 3952c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[0] = L = flags0&7; 3962c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org for (n=0,i=15-L;i<15;++i) { 3972c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org n |= ctx->nonce.c[i]; 3982c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[i]=0; 3992c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org n <<= 8; 4002c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 4012c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org n |= ctx->nonce.c[15]; /* reconstructed length */ 4022c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[15]=1; 4032c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 4042c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (n!=len) return -1; 4052c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 4062c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if ((n=len/16)) { 4072c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (*stream)(inp,out,n,key,ctx->nonce.c,ctx->cmac.c); 4082c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org n *= 16; 4092c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org inp += n; 4102c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org out += n; 4112c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org len -= n; 4122c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (len) ctr64_add(ctx->nonce.c,n/16); 4132c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 4142c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 4152c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (len) { 4162c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (*block)(ctx->nonce.c,scratch.c,key); 4172c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org for (i=0; i<len; ++i) 4182c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.c[i] ^= (out[i] = scratch.c[i]^inp[i]); 4192c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (*block)(ctx->cmac.c,ctx->cmac.c,key); 4202c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org } 4212c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 4222c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org for (i=15-L;i<16;++i) 4232c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[i]=0; 4242c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 4252c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org (*block)(ctx->nonce.c,scratch.c,key); 4262c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.u[0] ^= scratch.u[0]; 4272c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->cmac.u[1] ^= scratch.u[1]; 4282c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 4292c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org ctx->nonce.c[0] = flags0; 4302c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 4312c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org return 0; 4322c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org} 4332c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 4342c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.orgsize_t CRYPTO_ccm128_tag(CCM128_CONTEXT *ctx,unsigned char *tag,size_t len) 4352c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org{ unsigned int M = (ctx->nonce.c[0]>>3)&7; /* the M parameter */ 4362c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org 4372c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org M *= 2; M += 2; 4382c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org if (len<M) return 0; 4392c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org memcpy(tag,ctx->cmac.c,M); 4402c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org return M; 4412c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org} 442