LCOV - code coverage report
Current view: top level - third_party/openssl/crypto/modes - ccm128.c (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 0 222 0.0 %
Date: 2015-10-10 Functions: 0 9 0.0 %

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

Generated by: LCOV version 1.10