1238384Sjkim/* ==================================================================== 2238384Sjkim * Copyright (c) 2011 The OpenSSL Project. All rights reserved. 3238384Sjkim * 4238384Sjkim * Redistribution and use in source and binary forms, with or without 5238384Sjkim * modification, are permitted provided that the following conditions 6238384Sjkim * are met: 7238384Sjkim * 8238384Sjkim * 1. Redistributions of source code must retain the above copyright 9296341Sdelphij * notice, this list of conditions and the following disclaimer. 10238384Sjkim * 11238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright 12238384Sjkim * notice, this list of conditions and the following disclaimer in 13238384Sjkim * the documentation and/or other materials provided with the 14238384Sjkim * distribution. 15238384Sjkim * 16238384Sjkim * 3. All advertising materials mentioning features or use of this 17238384Sjkim * software must display the following acknowledgment: 18238384Sjkim * "This product includes software developed by the OpenSSL Project 19238384Sjkim * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 20238384Sjkim * 21238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 22238384Sjkim * endorse or promote products derived from this software without 23238384Sjkim * prior written permission. For written permission, please contact 24238384Sjkim * openssl-core@openssl.org. 25238384Sjkim * 26238384Sjkim * 5. Products derived from this software may not be called "OpenSSL" 27238384Sjkim * nor may "OpenSSL" appear in their names without prior written 28238384Sjkim * permission of the OpenSSL Project. 29238384Sjkim * 30238384Sjkim * 6. Redistributions of any form whatsoever must retain the following 31238384Sjkim * acknowledgment: 32238384Sjkim * "This product includes software developed by the OpenSSL Project 33238384Sjkim * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 34238384Sjkim * 35238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 36238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 38238384Sjkim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 39238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 40238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 41238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 42238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 43238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 44238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 45238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 46238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE. 47238384Sjkim * ==================================================================== 48238384Sjkim */ 49238384Sjkim 50238384Sjkim#include <openssl/crypto.h> 51238384Sjkim#include "modes_lcl.h" 52238384Sjkim#include <string.h> 53238384Sjkim 54238384Sjkim#ifndef MODES_DEBUG 55238384Sjkim# ifndef NDEBUG 56238384Sjkim# define NDEBUG 57238384Sjkim# endif 58238384Sjkim#endif 59238384Sjkim#include <assert.h> 60238384Sjkim 61296341Sdelphij/* 62296341Sdelphij * First you setup M and L parameters and pass the key schedule. This is 63296341Sdelphij * called once per session setup... 64296341Sdelphij */ 65238384Sjkimvoid CRYPTO_ccm128_init(CCM128_CONTEXT *ctx, 66296341Sdelphij unsigned int M, unsigned int L, void *key, 67296341Sdelphij block128_f block) 68238384Sjkim{ 69296341Sdelphij memset(ctx->nonce.c, 0, sizeof(ctx->nonce.c)); 70296341Sdelphij ctx->nonce.c[0] = ((u8)(L - 1) & 7) | (u8)(((M - 2) / 2) & 7) << 3; 71296341Sdelphij ctx->blocks = 0; 72296341Sdelphij ctx->block = block; 73296341Sdelphij ctx->key = key; 74238384Sjkim} 75238384Sjkim 76238384Sjkim/* !!! Following interfaces are to be called *once* per packet !!! */ 77238384Sjkim 78238384Sjkim/* Then you setup per-message nonce and pass the length of the message */ 79238384Sjkimint CRYPTO_ccm128_setiv(CCM128_CONTEXT *ctx, 80296341Sdelphij const unsigned char *nonce, size_t nlen, size_t mlen) 81238384Sjkim{ 82296341Sdelphij unsigned int L = ctx->nonce.c[0] & 7; /* the L parameter */ 83238384Sjkim 84296341Sdelphij if (nlen < (14 - L)) 85296341Sdelphij return -1; /* nonce is too short */ 86238384Sjkim 87296341Sdelphij if (sizeof(mlen) == 8 && L >= 3) { 88296341Sdelphij ctx->nonce.c[8] = (u8)(mlen >> (56 % (sizeof(mlen) * 8))); 89296341Sdelphij ctx->nonce.c[9] = (u8)(mlen >> (48 % (sizeof(mlen) * 8))); 90296341Sdelphij ctx->nonce.c[10] = (u8)(mlen >> (40 % (sizeof(mlen) * 8))); 91296341Sdelphij ctx->nonce.c[11] = (u8)(mlen >> (32 % (sizeof(mlen) * 8))); 92296341Sdelphij } else 93296341Sdelphij ctx->nonce.u[1] = 0; 94238384Sjkim 95296341Sdelphij ctx->nonce.c[12] = (u8)(mlen >> 24); 96296341Sdelphij ctx->nonce.c[13] = (u8)(mlen >> 16); 97296341Sdelphij ctx->nonce.c[14] = (u8)(mlen >> 8); 98296341Sdelphij ctx->nonce.c[15] = (u8)mlen; 99238384Sjkim 100296341Sdelphij ctx->nonce.c[0] &= ~0x40; /* clear Adata flag */ 101296341Sdelphij memcpy(&ctx->nonce.c[1], nonce, 14 - L); 102238384Sjkim 103296341Sdelphij return 0; 104238384Sjkim} 105238384Sjkim 106238384Sjkim/* Then you pass additional authentication data, this is optional */ 107238384Sjkimvoid CRYPTO_ccm128_aad(CCM128_CONTEXT *ctx, 108296341Sdelphij const unsigned char *aad, size_t alen) 109296341Sdelphij{ 110296341Sdelphij unsigned int i; 111296341Sdelphij block128_f block = ctx->block; 112238384Sjkim 113296341Sdelphij if (alen == 0) 114296341Sdelphij return; 115238384Sjkim 116296341Sdelphij ctx->nonce.c[0] |= 0x40; /* set Adata flag */ 117296341Sdelphij (*block) (ctx->nonce.c, ctx->cmac.c, ctx->key), ctx->blocks++; 118238384Sjkim 119296341Sdelphij if (alen < (0x10000 - 0x100)) { 120296341Sdelphij ctx->cmac.c[0] ^= (u8)(alen >> 8); 121296341Sdelphij ctx->cmac.c[1] ^= (u8)alen; 122296341Sdelphij i = 2; 123296341Sdelphij } else if (sizeof(alen) == 8 124296341Sdelphij && alen >= (size_t)1 << (32 % (sizeof(alen) * 8))) { 125296341Sdelphij ctx->cmac.c[0] ^= 0xFF; 126296341Sdelphij ctx->cmac.c[1] ^= 0xFF; 127296341Sdelphij ctx->cmac.c[2] ^= (u8)(alen >> (56 % (sizeof(alen) * 8))); 128296341Sdelphij ctx->cmac.c[3] ^= (u8)(alen >> (48 % (sizeof(alen) * 8))); 129296341Sdelphij ctx->cmac.c[4] ^= (u8)(alen >> (40 % (sizeof(alen) * 8))); 130296341Sdelphij ctx->cmac.c[5] ^= (u8)(alen >> (32 % (sizeof(alen) * 8))); 131296341Sdelphij ctx->cmac.c[6] ^= (u8)(alen >> 24); 132296341Sdelphij ctx->cmac.c[7] ^= (u8)(alen >> 16); 133296341Sdelphij ctx->cmac.c[8] ^= (u8)(alen >> 8); 134296341Sdelphij ctx->cmac.c[9] ^= (u8)alen; 135296341Sdelphij i = 10; 136296341Sdelphij } else { 137296341Sdelphij ctx->cmac.c[0] ^= 0xFF; 138296341Sdelphij ctx->cmac.c[1] ^= 0xFE; 139296341Sdelphij ctx->cmac.c[2] ^= (u8)(alen >> 24); 140296341Sdelphij ctx->cmac.c[3] ^= (u8)(alen >> 16); 141296341Sdelphij ctx->cmac.c[4] ^= (u8)(alen >> 8); 142296341Sdelphij ctx->cmac.c[5] ^= (u8)alen; 143296341Sdelphij i = 6; 144296341Sdelphij } 145238384Sjkim 146296341Sdelphij do { 147296341Sdelphij for (; i < 16 && alen; ++i, ++aad, --alen) 148296341Sdelphij ctx->cmac.c[i] ^= *aad; 149296341Sdelphij (*block) (ctx->cmac.c, ctx->cmac.c, ctx->key), ctx->blocks++; 150296341Sdelphij i = 0; 151296341Sdelphij } while (alen); 152238384Sjkim} 153238384Sjkim 154238384Sjkim/* Finally you encrypt or decrypt the message */ 155238384Sjkim 156296341Sdelphij/* 157296341Sdelphij * counter part of nonce may not be larger than L*8 bits, L is not larger 158296341Sdelphij * than 8, therefore 64-bit counter... 159296341Sdelphij */ 160296341Sdelphijstatic void ctr64_inc(unsigned char *counter) 161296341Sdelphij{ 162296341Sdelphij unsigned int n = 8; 163296341Sdelphij u8 c; 164238384Sjkim 165296341Sdelphij counter += 8; 166296341Sdelphij do { 167296341Sdelphij --n; 168296341Sdelphij c = counter[n]; 169296341Sdelphij ++c; 170296341Sdelphij counter[n] = c; 171296341Sdelphij if (c) 172296341Sdelphij return; 173296341Sdelphij } while (n); 174238384Sjkim} 175238384Sjkim 176238384Sjkimint CRYPTO_ccm128_encrypt(CCM128_CONTEXT *ctx, 177296341Sdelphij const unsigned char *inp, unsigned char *out, 178296341Sdelphij size_t len) 179238384Sjkim{ 180296341Sdelphij size_t n; 181296341Sdelphij unsigned int i, L; 182296341Sdelphij unsigned char flags0 = ctx->nonce.c[0]; 183296341Sdelphij block128_f block = ctx->block; 184296341Sdelphij void *key = ctx->key; 185296341Sdelphij union { 186296341Sdelphij u64 u[2]; 187296341Sdelphij u8 c[16]; 188296341Sdelphij } scratch; 189238384Sjkim 190296341Sdelphij if (!(flags0 & 0x40)) 191296341Sdelphij (*block) (ctx->nonce.c, ctx->cmac.c, key), ctx->blocks++; 192238384Sjkim 193296341Sdelphij ctx->nonce.c[0] = L = flags0 & 7; 194296341Sdelphij for (n = 0, i = 15 - L; i < 15; ++i) { 195296341Sdelphij n |= ctx->nonce.c[i]; 196296341Sdelphij ctx->nonce.c[i] = 0; 197296341Sdelphij n <<= 8; 198296341Sdelphij } 199296341Sdelphij n |= ctx->nonce.c[15]; /* reconstructed length */ 200296341Sdelphij ctx->nonce.c[15] = 1; 201238384Sjkim 202296341Sdelphij if (n != len) 203296341Sdelphij return -1; /* length mismatch */ 204238384Sjkim 205296341Sdelphij ctx->blocks += ((len + 15) >> 3) | 1; 206296341Sdelphij if (ctx->blocks > (U64(1) << 61)) 207296341Sdelphij return -2; /* too much data */ 208238384Sjkim 209296341Sdelphij while (len >= 16) { 210238384Sjkim#if defined(STRICT_ALIGNMENT) 211296341Sdelphij union { 212296341Sdelphij u64 u[2]; 213296341Sdelphij u8 c[16]; 214296341Sdelphij } temp; 215238384Sjkim 216296341Sdelphij memcpy(temp.c, inp, 16); 217296341Sdelphij ctx->cmac.u[0] ^= temp.u[0]; 218296341Sdelphij ctx->cmac.u[1] ^= temp.u[1]; 219238384Sjkim#else 220296341Sdelphij ctx->cmac.u[0] ^= ((u64 *)inp)[0]; 221296341Sdelphij ctx->cmac.u[1] ^= ((u64 *)inp)[1]; 222238384Sjkim#endif 223296341Sdelphij (*block) (ctx->cmac.c, ctx->cmac.c, key); 224296341Sdelphij (*block) (ctx->nonce.c, scratch.c, key); 225296341Sdelphij ctr64_inc(ctx->nonce.c); 226238384Sjkim#if defined(STRICT_ALIGNMENT) 227296341Sdelphij temp.u[0] ^= scratch.u[0]; 228296341Sdelphij temp.u[1] ^= scratch.u[1]; 229296341Sdelphij memcpy(out, temp.c, 16); 230238384Sjkim#else 231296341Sdelphij ((u64 *)out)[0] = scratch.u[0] ^ ((u64 *)inp)[0]; 232296341Sdelphij ((u64 *)out)[1] = scratch.u[1] ^ ((u64 *)inp)[1]; 233238384Sjkim#endif 234296341Sdelphij inp += 16; 235296341Sdelphij out += 16; 236296341Sdelphij len -= 16; 237296341Sdelphij } 238238384Sjkim 239296341Sdelphij if (len) { 240296341Sdelphij for (i = 0; i < len; ++i) 241296341Sdelphij ctx->cmac.c[i] ^= inp[i]; 242296341Sdelphij (*block) (ctx->cmac.c, ctx->cmac.c, key); 243296341Sdelphij (*block) (ctx->nonce.c, scratch.c, key); 244296341Sdelphij for (i = 0; i < len; ++i) 245296341Sdelphij out[i] = scratch.c[i] ^ inp[i]; 246296341Sdelphij } 247238384Sjkim 248296341Sdelphij for (i = 15 - L; i < 16; ++i) 249296341Sdelphij ctx->nonce.c[i] = 0; 250238384Sjkim 251296341Sdelphij (*block) (ctx->nonce.c, scratch.c, key); 252296341Sdelphij ctx->cmac.u[0] ^= scratch.u[0]; 253296341Sdelphij ctx->cmac.u[1] ^= scratch.u[1]; 254238384Sjkim 255296341Sdelphij ctx->nonce.c[0] = flags0; 256238384Sjkim 257296341Sdelphij return 0; 258238384Sjkim} 259238384Sjkim 260238384Sjkimint CRYPTO_ccm128_decrypt(CCM128_CONTEXT *ctx, 261296341Sdelphij const unsigned char *inp, unsigned char *out, 262296341Sdelphij size_t len) 263238384Sjkim{ 264296341Sdelphij size_t n; 265296341Sdelphij unsigned int i, L; 266296341Sdelphij unsigned char flags0 = ctx->nonce.c[0]; 267296341Sdelphij block128_f block = ctx->block; 268296341Sdelphij void *key = ctx->key; 269296341Sdelphij union { 270296341Sdelphij u64 u[2]; 271296341Sdelphij u8 c[16]; 272296341Sdelphij } scratch; 273238384Sjkim 274296341Sdelphij if (!(flags0 & 0x40)) 275296341Sdelphij (*block) (ctx->nonce.c, ctx->cmac.c, key); 276238384Sjkim 277296341Sdelphij ctx->nonce.c[0] = L = flags0 & 7; 278296341Sdelphij for (n = 0, i = 15 - L; i < 15; ++i) { 279296341Sdelphij n |= ctx->nonce.c[i]; 280296341Sdelphij ctx->nonce.c[i] = 0; 281296341Sdelphij n <<= 8; 282296341Sdelphij } 283296341Sdelphij n |= ctx->nonce.c[15]; /* reconstructed length */ 284296341Sdelphij ctx->nonce.c[15] = 1; 285238384Sjkim 286296341Sdelphij if (n != len) 287296341Sdelphij return -1; 288238384Sjkim 289296341Sdelphij while (len >= 16) { 290238384Sjkim#if defined(STRICT_ALIGNMENT) 291296341Sdelphij union { 292296341Sdelphij u64 u[2]; 293296341Sdelphij u8 c[16]; 294296341Sdelphij } temp; 295238384Sjkim#endif 296296341Sdelphij (*block) (ctx->nonce.c, scratch.c, key); 297296341Sdelphij ctr64_inc(ctx->nonce.c); 298238384Sjkim#if defined(STRICT_ALIGNMENT) 299296341Sdelphij memcpy(temp.c, inp, 16); 300296341Sdelphij ctx->cmac.u[0] ^= (scratch.u[0] ^= temp.u[0]); 301296341Sdelphij ctx->cmac.u[1] ^= (scratch.u[1] ^= temp.u[1]); 302296341Sdelphij memcpy(out, scratch.c, 16); 303238384Sjkim#else 304296341Sdelphij ctx->cmac.u[0] ^= (((u64 *)out)[0] = scratch.u[0] ^ ((u64 *)inp)[0]); 305296341Sdelphij ctx->cmac.u[1] ^= (((u64 *)out)[1] = scratch.u[1] ^ ((u64 *)inp)[1]); 306238384Sjkim#endif 307296341Sdelphij (*block) (ctx->cmac.c, ctx->cmac.c, key); 308238384Sjkim 309296341Sdelphij inp += 16; 310296341Sdelphij out += 16; 311296341Sdelphij len -= 16; 312296341Sdelphij } 313238384Sjkim 314296341Sdelphij if (len) { 315296341Sdelphij (*block) (ctx->nonce.c, scratch.c, key); 316296341Sdelphij for (i = 0; i < len; ++i) 317296341Sdelphij ctx->cmac.c[i] ^= (out[i] = scratch.c[i] ^ inp[i]); 318296341Sdelphij (*block) (ctx->cmac.c, ctx->cmac.c, key); 319296341Sdelphij } 320238384Sjkim 321296341Sdelphij for (i = 15 - L; i < 16; ++i) 322296341Sdelphij ctx->nonce.c[i] = 0; 323238384Sjkim 324296341Sdelphij (*block) (ctx->nonce.c, scratch.c, key); 325296341Sdelphij ctx->cmac.u[0] ^= scratch.u[0]; 326296341Sdelphij ctx->cmac.u[1] ^= scratch.u[1]; 327238384Sjkim 328296341Sdelphij ctx->nonce.c[0] = flags0; 329238384Sjkim 330296341Sdelphij return 0; 331238384Sjkim} 332238384Sjkim 333296341Sdelphijstatic void ctr64_add(unsigned char *counter, size_t inc) 334296341Sdelphij{ 335296341Sdelphij size_t n = 8, val = 0; 336238384Sjkim 337296341Sdelphij counter += 8; 338296341Sdelphij do { 339296341Sdelphij --n; 340296341Sdelphij val += counter[n] + (inc & 0xff); 341296341Sdelphij counter[n] = (unsigned char)val; 342296341Sdelphij val >>= 8; /* carry bit */ 343296341Sdelphij inc >>= 8; 344296341Sdelphij } while (n && (inc || val)); 345238384Sjkim} 346238384Sjkim 347238384Sjkimint CRYPTO_ccm128_encrypt_ccm64(CCM128_CONTEXT *ctx, 348296341Sdelphij const unsigned char *inp, unsigned char *out, 349296341Sdelphij size_t len, ccm128_f stream) 350238384Sjkim{ 351296341Sdelphij size_t n; 352296341Sdelphij unsigned int i, L; 353296341Sdelphij unsigned char flags0 = ctx->nonce.c[0]; 354296341Sdelphij block128_f block = ctx->block; 355296341Sdelphij void *key = ctx->key; 356296341Sdelphij union { 357296341Sdelphij u64 u[2]; 358296341Sdelphij u8 c[16]; 359296341Sdelphij } scratch; 360238384Sjkim 361296341Sdelphij if (!(flags0 & 0x40)) 362296341Sdelphij (*block) (ctx->nonce.c, ctx->cmac.c, key), ctx->blocks++; 363238384Sjkim 364296341Sdelphij ctx->nonce.c[0] = L = flags0 & 7; 365296341Sdelphij for (n = 0, i = 15 - L; i < 15; ++i) { 366296341Sdelphij n |= ctx->nonce.c[i]; 367296341Sdelphij ctx->nonce.c[i] = 0; 368296341Sdelphij n <<= 8; 369296341Sdelphij } 370296341Sdelphij n |= ctx->nonce.c[15]; /* reconstructed length */ 371296341Sdelphij ctx->nonce.c[15] = 1; 372238384Sjkim 373296341Sdelphij if (n != len) 374296341Sdelphij return -1; /* length mismatch */ 375238384Sjkim 376296341Sdelphij ctx->blocks += ((len + 15) >> 3) | 1; 377296341Sdelphij if (ctx->blocks > (U64(1) << 61)) 378296341Sdelphij return -2; /* too much data */ 379238384Sjkim 380296341Sdelphij if ((n = len / 16)) { 381296341Sdelphij (*stream) (inp, out, n, key, ctx->nonce.c, ctx->cmac.c); 382296341Sdelphij n *= 16; 383296341Sdelphij inp += n; 384296341Sdelphij out += n; 385296341Sdelphij len -= n; 386296341Sdelphij if (len) 387296341Sdelphij ctr64_add(ctx->nonce.c, n / 16); 388296341Sdelphij } 389238384Sjkim 390296341Sdelphij if (len) { 391296341Sdelphij for (i = 0; i < len; ++i) 392296341Sdelphij ctx->cmac.c[i] ^= inp[i]; 393296341Sdelphij (*block) (ctx->cmac.c, ctx->cmac.c, key); 394296341Sdelphij (*block) (ctx->nonce.c, scratch.c, key); 395296341Sdelphij for (i = 0; i < len; ++i) 396296341Sdelphij out[i] = scratch.c[i] ^ inp[i]; 397296341Sdelphij } 398238384Sjkim 399296341Sdelphij for (i = 15 - L; i < 16; ++i) 400296341Sdelphij ctx->nonce.c[i] = 0; 401238384Sjkim 402296341Sdelphij (*block) (ctx->nonce.c, scratch.c, key); 403296341Sdelphij ctx->cmac.u[0] ^= scratch.u[0]; 404296341Sdelphij ctx->cmac.u[1] ^= scratch.u[1]; 405238384Sjkim 406296341Sdelphij ctx->nonce.c[0] = flags0; 407238384Sjkim 408296341Sdelphij return 0; 409238384Sjkim} 410238384Sjkim 411238384Sjkimint CRYPTO_ccm128_decrypt_ccm64(CCM128_CONTEXT *ctx, 412296341Sdelphij const unsigned char *inp, unsigned char *out, 413296341Sdelphij size_t len, ccm128_f stream) 414238384Sjkim{ 415296341Sdelphij size_t n; 416296341Sdelphij unsigned int i, L; 417296341Sdelphij unsigned char flags0 = ctx->nonce.c[0]; 418296341Sdelphij block128_f block = ctx->block; 419296341Sdelphij void *key = ctx->key; 420296341Sdelphij union { 421296341Sdelphij u64 u[2]; 422296341Sdelphij u8 c[16]; 423296341Sdelphij } scratch; 424238384Sjkim 425296341Sdelphij if (!(flags0 & 0x40)) 426296341Sdelphij (*block) (ctx->nonce.c, ctx->cmac.c, key); 427238384Sjkim 428296341Sdelphij ctx->nonce.c[0] = L = flags0 & 7; 429296341Sdelphij for (n = 0, i = 15 - L; i < 15; ++i) { 430296341Sdelphij n |= ctx->nonce.c[i]; 431296341Sdelphij ctx->nonce.c[i] = 0; 432296341Sdelphij n <<= 8; 433296341Sdelphij } 434296341Sdelphij n |= ctx->nonce.c[15]; /* reconstructed length */ 435296341Sdelphij ctx->nonce.c[15] = 1; 436238384Sjkim 437296341Sdelphij if (n != len) 438296341Sdelphij return -1; 439238384Sjkim 440296341Sdelphij if ((n = len / 16)) { 441296341Sdelphij (*stream) (inp, out, n, key, ctx->nonce.c, ctx->cmac.c); 442296341Sdelphij n *= 16; 443296341Sdelphij inp += n; 444296341Sdelphij out += n; 445296341Sdelphij len -= n; 446296341Sdelphij if (len) 447296341Sdelphij ctr64_add(ctx->nonce.c, n / 16); 448296341Sdelphij } 449238384Sjkim 450296341Sdelphij if (len) { 451296341Sdelphij (*block) (ctx->nonce.c, scratch.c, key); 452296341Sdelphij for (i = 0; i < len; ++i) 453296341Sdelphij ctx->cmac.c[i] ^= (out[i] = scratch.c[i] ^ inp[i]); 454296341Sdelphij (*block) (ctx->cmac.c, ctx->cmac.c, key); 455296341Sdelphij } 456238384Sjkim 457296341Sdelphij for (i = 15 - L; i < 16; ++i) 458296341Sdelphij ctx->nonce.c[i] = 0; 459238384Sjkim 460296341Sdelphij (*block) (ctx->nonce.c, scratch.c, key); 461296341Sdelphij ctx->cmac.u[0] ^= scratch.u[0]; 462296341Sdelphij ctx->cmac.u[1] ^= scratch.u[1]; 463238384Sjkim 464296341Sdelphij ctx->nonce.c[0] = flags0; 465238384Sjkim 466296341Sdelphij return 0; 467238384Sjkim} 468238384Sjkim 469296341Sdelphijsize_t CRYPTO_ccm128_tag(CCM128_CONTEXT *ctx, unsigned char *tag, size_t len) 470296341Sdelphij{ 471296341Sdelphij unsigned int M = (ctx->nonce.c[0] >> 3) & 7; /* the M parameter */ 472238384Sjkim 473296341Sdelphij M *= 2; 474296341Sdelphij M += 2; 475296341Sdelphij if (len < M) 476296341Sdelphij return 0; 477296341Sdelphij memcpy(tag, ctx->cmac.c, M); 478296341Sdelphij return M; 479238384Sjkim} 480