LCOV - code coverage report
Current view: top level - cipher - cipher-aeswrap.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 62 77 80.5 %
Date: 2017-03-02 16:44:37 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /* cipher-aeswrap.c  - Generic AESWRAP mode implementation
       2             :  * Copyright (C) 2009, 2011 Free Software Foundation, Inc.
       3             :  *
       4             :  * This file is part of Libgcrypt.
       5             :  *
       6             :  * Libgcrypt is free software; you can redistribute it and/or modify
       7             :  * it under the terms of the GNU Lesser general Public License as
       8             :  * published by the Free Software Foundation; either version 2.1 of
       9             :  * the License, or (at your option) any later version.
      10             :  *
      11             :  * Libgcrypt is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  * GNU Lesser General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU Lesser General Public
      17             :  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #include <config.h>
      21             : #include <stdio.h>
      22             : #include <stdlib.h>
      23             : #include <string.h>
      24             : #include <errno.h>
      25             : 
      26             : #include "g10lib.h"
      27             : #include "cipher.h"
      28             : #include "bufhelp.h"
      29             : #include "./cipher-internal.h"
      30             : 
      31             : 
      32             : /* Perform the AES-Wrap algorithm as specified by RFC3394.  We
      33             :    implement this as a mode usable with any cipher algorithm of
      34             :    blocksize 128.  */
      35             : gcry_err_code_t
      36           6 : _gcry_cipher_aeswrap_encrypt (gcry_cipher_hd_t c,
      37             :                               byte *outbuf, size_t outbuflen,
      38             :                               const byte *inbuf, size_t inbuflen )
      39             : {
      40             :   int j, x;
      41             :   size_t n, i;
      42             :   unsigned char *r, *a, *b;
      43             :   unsigned char t[8];
      44             :   unsigned int burn, nburn;
      45             : 
      46             : #if MAX_BLOCKSIZE < 8
      47             : #error Invalid block size
      48             : #endif
      49             :   /* We require a cipher with a 128 bit block length.  */
      50           6 :   if (c->spec->blocksize != 16)
      51           0 :     return GPG_ERR_INV_LENGTH;
      52             : 
      53             :   /* The output buffer must be able to hold the input data plus one
      54             :      additional block.  */
      55           6 :   if (outbuflen < inbuflen + 8)
      56           0 :     return GPG_ERR_BUFFER_TOO_SHORT;
      57             :   /* Input data must be multiple of 64 bits.  */
      58           6 :   if (inbuflen % 8)
      59           0 :     return GPG_ERR_INV_ARG;
      60             : 
      61           6 :   n = inbuflen / 8;
      62             : 
      63             :   /* We need at least two 64 bit blocks.  */
      64           6 :   if (n < 2)
      65           0 :     return GPG_ERR_INV_ARG;
      66             : 
      67           6 :   burn = 0;
      68             : 
      69           6 :   r = outbuf;
      70           6 :   a = outbuf;  /* We store A directly in OUTBUF.  */
      71           6 :   b = c->u_ctr.ctr;  /* B is also used to concatenate stuff.  */
      72             : 
      73             :   /* If an IV has been set we use that IV as the Alternative Initial
      74             :      Value; if it has not been set we use the standard value.  */
      75           6 :   if (c->marks.iv)
      76           0 :     memcpy (a, c->u_iv.iv, 8);
      77             :   else
      78           6 :     memset (a, 0xa6, 8);
      79             : 
      80             :   /* Copy the inbuf to the outbuf. */
      81           6 :   memmove (r+8, inbuf, inbuflen);
      82             : 
      83           6 :   memset (t, 0, sizeof t); /* t := 0.  */
      84             : 
      85          42 :   for (j = 0; j <= 5; j++)
      86             :     {
      87         132 :       for (i = 1; i <= n; i++)
      88             :         {
      89             :           /* B := AES_k( A | R[i] ) */
      90          96 :           memcpy (b, a, 8);
      91          96 :           memcpy (b+8, r+i*8, 8);
      92          96 :           nburn = c->spec->encrypt (&c->context.c, b, b);
      93          96 :           burn = nburn > burn ? nburn : burn;
      94             :           /* t := t + 1  */
      95          96 :           for (x = 7; x >= 0; x--)
      96             :             {
      97          96 :               t[x]++;
      98          96 :               if (t[x])
      99          96 :                 break;
     100             :             }
     101             :           /* A := MSB_64(B) ^ t */
     102          96 :           buf_xor(a, b, t, 8);
     103             :           /* R[i] := LSB_64(B) */
     104          96 :           memcpy (r+i*8, b+8, 8);
     105             :         }
     106             :    }
     107             : 
     108           6 :   if (burn > 0)
     109           0 :     _gcry_burn_stack (burn + 4 * sizeof(void *));
     110             : 
     111           6 :   return 0;
     112             : }
     113             : 
     114             : /* Perform the AES-Unwrap algorithm as specified by RFC3394.  We
     115             :    implement this as a mode usable with any cipher algorithm of
     116             :    blocksize 128.  */
     117             : gcry_err_code_t
     118          18 : _gcry_cipher_aeswrap_decrypt (gcry_cipher_hd_t c,
     119             :                               byte *outbuf, size_t outbuflen,
     120             :                               const byte *inbuf, size_t inbuflen)
     121             : {
     122             :   int j, x;
     123             :   size_t n, i;
     124             :   unsigned char *r, *a, *b;
     125             :   unsigned char t[8];
     126             :   unsigned int burn, nburn;
     127             : 
     128             : #if MAX_BLOCKSIZE < 8
     129             : #error Invalid block size
     130             : #endif
     131             :   /* We require a cipher with a 128 bit block length.  */
     132          18 :   if (c->spec->blocksize != 16)
     133           0 :     return GPG_ERR_INV_LENGTH;
     134             : 
     135             :   /* The output buffer must be able to hold the input data minus one
     136             :      additional block.  Fixme: The caller has more restrictive checks
     137             :      - we may want to fix them for this mode.  */
     138          18 :   if (outbuflen + 8  < inbuflen)
     139           0 :     return GPG_ERR_BUFFER_TOO_SHORT;
     140             :   /* Input data must be multiple of 64 bits.  */
     141          18 :   if (inbuflen % 8)
     142           0 :     return GPG_ERR_INV_ARG;
     143             : 
     144          18 :   n = inbuflen / 8;
     145             : 
     146             :   /* We need at least three 64 bit blocks.  */
     147          18 :   if (n < 3)
     148           0 :     return GPG_ERR_INV_ARG;
     149             : 
     150          18 :   burn = 0;
     151             : 
     152          18 :   r = outbuf;
     153          18 :   a = c->lastiv;  /* We use c->LASTIV as buffer for A.  */
     154          18 :   b = c->u_ctr.ctr;     /* B is also used to concatenate stuff.  */
     155             : 
     156             :   /* Copy the inbuf to the outbuf and save A. */
     157          18 :   memcpy (a, inbuf, 8);
     158          18 :   memmove (r, inbuf+8, inbuflen-8);
     159          18 :   n--; /* Reduce to actual number of data blocks.  */
     160             : 
     161             :   /* t := 6 * n  */
     162          18 :   i = n * 6;  /* The range is valid because: n = inbuflen / 8 - 1.  */
     163         162 :   for (x=0; x < 8 && x < sizeof (i); x++)
     164         144 :     t[7-x] = i >> (8*x);
     165          18 :   for (; x < 8; x++)
     166           0 :     t[7-x] = 0;
     167             : 
     168         126 :   for (j = 5; j >= 0; j--)
     169             :     {
     170         396 :       for (i = n; i >= 1; i--)
     171             :         {
     172             :           /* B := AES_k^1( (A ^ t)| R[i] ) */
     173         288 :           buf_xor(b, a, t, 8);
     174         288 :           memcpy (b+8, r+(i-1)*8, 8);
     175         288 :           nburn = c->spec->decrypt (&c->context.c, b, b);
     176         288 :           burn = nburn > burn ? nburn : burn;
     177             :           /* t := t - 1  */
     178         288 :           for (x = 7; x >= 0; x--)
     179             :             {
     180         288 :               t[x]--;
     181         288 :               if (t[x] != 0xff)
     182         288 :                 break;
     183             :             }
     184             :           /* A := MSB_64(B) */
     185         288 :           memcpy (a, b, 8);
     186             :           /* R[i] := LSB_64(B) */
     187         288 :           memcpy (r+(i-1)*8, b+8, 8);
     188             :         }
     189             :    }
     190             : 
     191             :   /* If an IV has been set we compare against this Alternative Initial
     192             :      Value; if it has not been set we compare against the standard IV.  */
     193          18 :   if (c->marks.iv)
     194           0 :     j = memcmp (a, c->u_iv.iv, 8);
     195             :   else
     196             :     {
     197         162 :       for (j=0, x=0; x < 8; x++)
     198         144 :         if (a[x] != 0xa6)
     199             :           {
     200           0 :             j=1;
     201           0 :             break;
     202             :           }
     203             :     }
     204             : 
     205          18 :   if (burn > 0)
     206           0 :     _gcry_burn_stack (burn + 4 * sizeof(void *));
     207             : 
     208          18 :   return j? GPG_ERR_CHECKSUM : 0;
     209             : }

Generated by: LCOV version 1.13