LCOV - code coverage report
Current view: top level - cipher - cipher-gcm.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 284 0.0 %
Date: 2016-12-15 12:59:22 Functions: 0 20 0.0 %

          Line data    Source code
       1             : /* cipher-gcm.c  - Generic Galois Counter Mode implementation
       2             :  * Copyright (C) 2013 Dmitry Eremin-Solenikov
       3             :  * Copyright (C) 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi>
       4             :  *
       5             :  * This file is part of Libgcrypt.
       6             :  *
       7             :  * Libgcrypt is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU Lesser general Public License as
       9             :  * published by the Free Software Foundation; either version 2.1 of
      10             :  * the License, or (at your option) any later version.
      11             :  *
      12             :  * Libgcrypt is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU Lesser General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU Lesser General Public
      18             :  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include <config.h>
      22             : #include <stdio.h>
      23             : #include <stdlib.h>
      24             : #include <string.h>
      25             : #include <errno.h>
      26             : 
      27             : #include "g10lib.h"
      28             : #include "cipher.h"
      29             : #include "bufhelp.h"
      30             : #include "./cipher-internal.h"
      31             : 
      32             : 
      33             : #ifdef GCM_USE_INTEL_PCLMUL
      34             : extern void _gcry_ghash_setup_intel_pclmul (gcry_cipher_hd_t c);
      35             : 
      36             : extern unsigned int _gcry_ghash_intel_pclmul (gcry_cipher_hd_t c, byte *result,
      37             :                                               const byte *buf, size_t nblocks);
      38             : #endif
      39             : 
      40             : #ifdef GCM_USE_ARM_PMULL
      41             : extern void _gcry_ghash_setup_armv8_ce_pmull (void *gcm_key, void *gcm_table);
      42             : 
      43             : extern unsigned int _gcry_ghash_armv8_ce_pmull (void *gcm_key, byte *result,
      44             :                                                 const byte *buf, size_t nblocks,
      45             :                                                 void *gcm_table);
      46             : 
      47             : static void
      48             : ghash_setup_armv8_ce_pmull (gcry_cipher_hd_t c)
      49             : {
      50             :   _gcry_ghash_setup_armv8_ce_pmull(c->u_mode.gcm.u_ghash_key.key,
      51             :                                    c->u_mode.gcm.gcm_table);
      52             : }
      53             : 
      54             : static unsigned int
      55             : ghash_armv8_ce_pmull (gcry_cipher_hd_t c, byte *result, const byte *buf,
      56             :                       size_t nblocks)
      57             : {
      58             :   return _gcry_ghash_armv8_ce_pmull(c->u_mode.gcm.u_ghash_key.key, result, buf,
      59             :                                     nblocks, c->u_mode.gcm.gcm_table);
      60             : }
      61             : 
      62             : #endif
      63             : 
      64             : 
      65             : #ifdef GCM_USE_TABLES
      66             : static const u16 gcmR[256] = {
      67             :   0x0000, 0x01c2, 0x0384, 0x0246, 0x0708, 0x06ca, 0x048c, 0x054e,
      68             :   0x0e10, 0x0fd2, 0x0d94, 0x0c56, 0x0918, 0x08da, 0x0a9c, 0x0b5e,
      69             :   0x1c20, 0x1de2, 0x1fa4, 0x1e66, 0x1b28, 0x1aea, 0x18ac, 0x196e,
      70             :   0x1230, 0x13f2, 0x11b4, 0x1076, 0x1538, 0x14fa, 0x16bc, 0x177e,
      71             :   0x3840, 0x3982, 0x3bc4, 0x3a06, 0x3f48, 0x3e8a, 0x3ccc, 0x3d0e,
      72             :   0x3650, 0x3792, 0x35d4, 0x3416, 0x3158, 0x309a, 0x32dc, 0x331e,
      73             :   0x2460, 0x25a2, 0x27e4, 0x2626, 0x2368, 0x22aa, 0x20ec, 0x212e,
      74             :   0x2a70, 0x2bb2, 0x29f4, 0x2836, 0x2d78, 0x2cba, 0x2efc, 0x2f3e,
      75             :   0x7080, 0x7142, 0x7304, 0x72c6, 0x7788, 0x764a, 0x740c, 0x75ce,
      76             :   0x7e90, 0x7f52, 0x7d14, 0x7cd6, 0x7998, 0x785a, 0x7a1c, 0x7bde,
      77             :   0x6ca0, 0x6d62, 0x6f24, 0x6ee6, 0x6ba8, 0x6a6a, 0x682c, 0x69ee,
      78             :   0x62b0, 0x6372, 0x6134, 0x60f6, 0x65b8, 0x647a, 0x663c, 0x67fe,
      79             :   0x48c0, 0x4902, 0x4b44, 0x4a86, 0x4fc8, 0x4e0a, 0x4c4c, 0x4d8e,
      80             :   0x46d0, 0x4712, 0x4554, 0x4496, 0x41d8, 0x401a, 0x425c, 0x439e,
      81             :   0x54e0, 0x5522, 0x5764, 0x56a6, 0x53e8, 0x522a, 0x506c, 0x51ae,
      82             :   0x5af0, 0x5b32, 0x5974, 0x58b6, 0x5df8, 0x5c3a, 0x5e7c, 0x5fbe,
      83             :   0xe100, 0xe0c2, 0xe284, 0xe346, 0xe608, 0xe7ca, 0xe58c, 0xe44e,
      84             :   0xef10, 0xeed2, 0xec94, 0xed56, 0xe818, 0xe9da, 0xeb9c, 0xea5e,
      85             :   0xfd20, 0xfce2, 0xfea4, 0xff66, 0xfa28, 0xfbea, 0xf9ac, 0xf86e,
      86             :   0xf330, 0xf2f2, 0xf0b4, 0xf176, 0xf438, 0xf5fa, 0xf7bc, 0xf67e,
      87             :   0xd940, 0xd882, 0xdac4, 0xdb06, 0xde48, 0xdf8a, 0xddcc, 0xdc0e,
      88             :   0xd750, 0xd692, 0xd4d4, 0xd516, 0xd058, 0xd19a, 0xd3dc, 0xd21e,
      89             :   0xc560, 0xc4a2, 0xc6e4, 0xc726, 0xc268, 0xc3aa, 0xc1ec, 0xc02e,
      90             :   0xcb70, 0xcab2, 0xc8f4, 0xc936, 0xcc78, 0xcdba, 0xcffc, 0xce3e,
      91             :   0x9180, 0x9042, 0x9204, 0x93c6, 0x9688, 0x974a, 0x950c, 0x94ce,
      92             :   0x9f90, 0x9e52, 0x9c14, 0x9dd6, 0x9898, 0x995a, 0x9b1c, 0x9ade,
      93             :   0x8da0, 0x8c62, 0x8e24, 0x8fe6, 0x8aa8, 0x8b6a, 0x892c, 0x88ee,
      94             :   0x83b0, 0x8272, 0x8034, 0x81f6, 0x84b8, 0x857a, 0x873c, 0x86fe,
      95             :   0xa9c0, 0xa802, 0xaa44, 0xab86, 0xaec8, 0xaf0a, 0xad4c, 0xac8e,
      96             :   0xa7d0, 0xa612, 0xa454, 0xa596, 0xa0d8, 0xa11a, 0xa35c, 0xa29e,
      97             :   0xb5e0, 0xb422, 0xb664, 0xb7a6, 0xb2e8, 0xb32a, 0xb16c, 0xb0ae,
      98             :   0xbbf0, 0xba32, 0xb874, 0xb9b6, 0xbcf8, 0xbd3a, 0xbf7c, 0xbebe,
      99             : };
     100             : 
     101             : #ifdef GCM_TABLES_USE_U64
     102             : static void
     103           0 : bshift (u64 * b0, u64 * b1)
     104             : {
     105             :   u64 t[2], mask;
     106             : 
     107           0 :   t[0] = *b0;
     108           0 :   t[1] = *b1;
     109           0 :   mask = t[1] & 1 ? 0xe1 : 0;
     110           0 :   mask <<= 56;
     111             : 
     112           0 :   *b1 = (t[1] >> 1) ^ (t[0] << 63);
     113           0 :   *b0 = (t[0] >> 1) ^ mask;
     114           0 : }
     115             : 
     116             : static void
     117           0 : do_fillM (unsigned char *h, u64 *M)
     118             : {
     119             :   int i, j;
     120             : 
     121           0 :   M[0 + 0] = 0;
     122           0 :   M[0 + 16] = 0;
     123             : 
     124           0 :   M[8 + 0] = buf_get_be64 (h + 0);
     125           0 :   M[8 + 16] = buf_get_be64 (h + 8);
     126             : 
     127           0 :   for (i = 4; i > 0; i /= 2)
     128             :     {
     129           0 :       M[i + 0] = M[2 * i + 0];
     130           0 :       M[i + 16] = M[2 * i + 16];
     131             : 
     132           0 :       bshift (&M[i], &M[i + 16]);
     133             :     }
     134             : 
     135           0 :   for (i = 2; i < 16; i *= 2)
     136           0 :     for (j = 1; j < i; j++)
     137             :       {
     138           0 :         M[(i + j) + 0] = M[i + 0] ^ M[j + 0];
     139           0 :         M[(i + j) + 16] = M[i + 16] ^ M[j + 16];
     140             :       }
     141           0 : }
     142             : 
     143             : static inline unsigned int
     144           0 : do_ghash (unsigned char *result, const unsigned char *buf, const u64 *gcmM)
     145             : {
     146             :   u64 V[2];
     147             :   u64 tmp[2];
     148             :   const u64 *M;
     149             :   u64 T;
     150             :   u32 A;
     151             :   int i;
     152             : 
     153           0 :   buf_xor (V, result, buf, 16);
     154           0 :   V[0] = be_bswap64 (V[0]);
     155           0 :   V[1] = be_bswap64 (V[1]);
     156             : 
     157             :   /* First round can be manually tweaked based on fact that 'tmp' is zero. */
     158           0 :   i = 15;
     159             : 
     160           0 :   M = &gcmM[(V[1] & 0xf)];
     161           0 :   V[1] >>= 4;
     162           0 :   tmp[0] = (M[0] >> 4) ^ ((u64) gcmR[(M[16] & 0xf) << 4] << 48);
     163           0 :   tmp[1] = (M[16] >> 4) ^ (M[0] << 60);
     164           0 :   tmp[0] ^= gcmM[(V[1] & 0xf) + 0];
     165           0 :   tmp[1] ^= gcmM[(V[1] & 0xf) + 16];
     166           0 :   V[1] >>= 4;
     167             : 
     168           0 :   --i;
     169             :   while (1)
     170             :     {
     171           0 :       M = &gcmM[(V[1] & 0xf)];
     172           0 :       V[1] >>= 4;
     173             : 
     174           0 :       A = tmp[1] & 0xff;
     175           0 :       T = tmp[0];
     176           0 :       tmp[0] = (T >> 8) ^ ((u64) gcmR[A] << 48) ^ gcmM[(V[1] & 0xf) + 0];
     177           0 :       tmp[1] = (T << 56) ^ (tmp[1] >> 8) ^ gcmM[(V[1] & 0xf) + 16];
     178             : 
     179           0 :       tmp[0] ^= (M[0] >> 4) ^ ((u64) gcmR[(M[16] & 0xf) << 4] << 48);
     180           0 :       tmp[1] ^= (M[16] >> 4) ^ (M[0] << 60);
     181             : 
     182           0 :       if (i == 0)
     183           0 :         break;
     184           0 :       else if (i == 8)
     185           0 :         V[1] = V[0];
     186             :       else
     187           0 :         V[1] >>= 4;
     188           0 :       --i;
     189             :     }
     190             : 
     191           0 :   buf_put_be64 (result + 0, tmp[0]);
     192           0 :   buf_put_be64 (result + 8, tmp[1]);
     193             : 
     194           0 :   return (sizeof(V) + sizeof(T) + sizeof(tmp) +
     195             :           sizeof(int)*2 + sizeof(void*)*5);
     196             : }
     197             : 
     198             : #else /*!GCM_TABLES_USE_U64*/
     199             : 
     200             : static void
     201             : bshift (u32 * M, int i)
     202             : {
     203             :   u32 t[4], mask;
     204             : 
     205             :   t[0] = M[i * 4 + 0];
     206             :   t[1] = M[i * 4 + 1];
     207             :   t[2] = M[i * 4 + 2];
     208             :   t[3] = M[i * 4 + 3];
     209             :   mask = t[3] & 1 ? 0xe1 : 0;
     210             : 
     211             :   M[i * 4 + 3] = (t[3] >> 1) ^ (t[2] << 31);
     212             :   M[i * 4 + 2] = (t[2] >> 1) ^ (t[1] << 31);
     213             :   M[i * 4 + 1] = (t[1] >> 1) ^ (t[0] << 31);
     214             :   M[i * 4 + 0] = (t[0] >> 1) ^ (mask << 24);
     215             : }
     216             : 
     217             : static void
     218             : do_fillM (unsigned char *h, u32 *M)
     219             : {
     220             :   int i, j;
     221             : 
     222             :   M[0 * 4 + 0] = 0;
     223             :   M[0 * 4 + 1] = 0;
     224             :   M[0 * 4 + 2] = 0;
     225             :   M[0 * 4 + 3] = 0;
     226             : 
     227             :   M[8 * 4 + 0] = buf_get_be32 (h + 0);
     228             :   M[8 * 4 + 1] = buf_get_be32 (h + 4);
     229             :   M[8 * 4 + 2] = buf_get_be32 (h + 8);
     230             :   M[8 * 4 + 3] = buf_get_be32 (h + 12);
     231             : 
     232             :   for (i = 4; i > 0; i /= 2)
     233             :     {
     234             :       M[i * 4 + 0] = M[2 * i * 4 + 0];
     235             :       M[i * 4 + 1] = M[2 * i * 4 + 1];
     236             :       M[i * 4 + 2] = M[2 * i * 4 + 2];
     237             :       M[i * 4 + 3] = M[2 * i * 4 + 3];
     238             : 
     239             :       bshift (M, i);
     240             :     }
     241             : 
     242             :   for (i = 2; i < 16; i *= 2)
     243             :     for (j = 1; j < i; j++)
     244             :       {
     245             :         M[(i + j) * 4 + 0] = M[i * 4 + 0] ^ M[j * 4 + 0];
     246             :         M[(i + j) * 4 + 1] = M[i * 4 + 1] ^ M[j * 4 + 1];
     247             :         M[(i + j) * 4 + 2] = M[i * 4 + 2] ^ M[j * 4 + 2];
     248             :         M[(i + j) * 4 + 3] = M[i * 4 + 3] ^ M[j * 4 + 3];
     249             :       }
     250             : }
     251             : 
     252             : static inline unsigned int
     253             : do_ghash (unsigned char *result, const unsigned char *buf, const u32 *gcmM)
     254             : {
     255             :   byte V[16];
     256             :   u32 tmp[4];
     257             :   u32 v;
     258             :   const u32 *M, *m;
     259             :   u32 T[3];
     260             :   int i;
     261             : 
     262             :   buf_xor (V, result, buf, 16); /* V is big-endian */
     263             : 
     264             :   /* First round can be manually tweaked based on fact that 'tmp' is zero. */
     265             :   i = 15;
     266             : 
     267             :   v = V[i];
     268             :   M = &gcmM[(v & 0xf) * 4];
     269             :   v = (v & 0xf0) >> 4;
     270             :   m = &gcmM[v * 4];
     271             :   v = V[--i];
     272             : 
     273             :   tmp[0] = (M[0] >> 4) ^ ((u64) gcmR[(M[3] << 4) & 0xf0] << 16) ^ m[0];
     274             :   tmp[1] = (M[1] >> 4) ^ (M[0] << 28) ^ m[1];
     275             :   tmp[2] = (M[2] >> 4) ^ (M[1] << 28) ^ m[2];
     276             :   tmp[3] = (M[3] >> 4) ^ (M[2] << 28) ^ m[3];
     277             : 
     278             :   while (1)
     279             :     {
     280             :       M = &gcmM[(v & 0xf) * 4];
     281             :       v = (v & 0xf0) >> 4;
     282             :       m = &gcmM[v * 4];
     283             : 
     284             :       T[0] = tmp[0];
     285             :       T[1] = tmp[1];
     286             :       T[2] = tmp[2];
     287             :       tmp[0] = (T[0] >> 8) ^ ((u32) gcmR[tmp[3] & 0xff] << 16) ^ m[0];
     288             :       tmp[1] = (T[0] << 24) ^ (tmp[1] >> 8) ^ m[1];
     289             :       tmp[2] = (T[1] << 24) ^ (tmp[2] >> 8) ^ m[2];
     290             :       tmp[3] = (T[2] << 24) ^ (tmp[3] >> 8) ^ m[3];
     291             : 
     292             :       tmp[0] ^= (M[0] >> 4) ^ ((u64) gcmR[(M[3] << 4) & 0xf0] << 16);
     293             :       tmp[1] ^= (M[1] >> 4) ^ (M[0] << 28);
     294             :       tmp[2] ^= (M[2] >> 4) ^ (M[1] << 28);
     295             :       tmp[3] ^= (M[3] >> 4) ^ (M[2] << 28);
     296             : 
     297             :       if (i == 0)
     298             :         break;
     299             : 
     300             :       v = V[--i];
     301             :     }
     302             : 
     303             :   buf_put_be32 (result + 0, tmp[0]);
     304             :   buf_put_be32 (result + 4, tmp[1]);
     305             :   buf_put_be32 (result + 8, tmp[2]);
     306             :   buf_put_be32 (result + 12, tmp[3]);
     307             : 
     308             :   return (sizeof(V) + sizeof(T) + sizeof(tmp) +
     309             :           sizeof(int)*2 + sizeof(void*)*6);
     310             : }
     311             : #endif /*!GCM_TABLES_USE_U64*/
     312             : 
     313             : #define fillM(c) \
     314             :   do_fillM (c->u_mode.gcm.u_ghash_key.key, c->u_mode.gcm.gcm_table)
     315             : #define GHASH(c, result, buf) do_ghash (result, buf, c->u_mode.gcm.gcm_table)
     316             : 
     317             : #else
     318             : 
     319             : static unsigned long
     320             : bshift (unsigned long *b)
     321             : {
     322             :   unsigned long c;
     323             :   int i;
     324             :   c = b[3] & 1;
     325             :   for (i = 3; i > 0; i--)
     326             :     {
     327             :       b[i] = (b[i] >> 1) | (b[i - 1] << 31);
     328             :     }
     329             :   b[i] >>= 1;
     330             :   return c;
     331             : }
     332             : 
     333             : static unsigned int
     334             : do_ghash (unsigned char *hsub, unsigned char *result, const unsigned char *buf)
     335             : {
     336             :   unsigned long V[4];
     337             :   int i, j;
     338             :   byte *p;
     339             : 
     340             : #ifdef WORDS_BIGENDIAN
     341             :   p = result;
     342             : #else
     343             :   unsigned long T[4];
     344             : 
     345             :   buf_xor (V, result, buf, 16);
     346             :   for (i = 0; i < 4; i++)
     347             :     {
     348             :       V[i] = (V[i] & 0x00ff00ff) << 8 | (V[i] & 0xff00ff00) >> 8;
     349             :       V[i] = (V[i] & 0x0000ffff) << 16 | (V[i] & 0xffff0000) >> 16;
     350             :     }
     351             :   p = (byte *) T;
     352             : #endif
     353             : 
     354             :   memset (p, 0, 16);
     355             : 
     356             :   for (i = 0; i < 16; i++)
     357             :     {
     358             :       for (j = 0x80; j; j >>= 1)
     359             :         {
     360             :           if (hsub[i] & j)
     361             :             buf_xor (p, p, V, 16);
     362             :           if (bshift (V))
     363             :             V[0] ^= 0xe1000000;
     364             :         }
     365             :     }
     366             : #ifndef WORDS_BIGENDIAN
     367             :   for (i = 0, p = (byte *) T; i < 16; i += 4, p += 4)
     368             :     {
     369             :       result[i + 0] = p[3];
     370             :       result[i + 1] = p[2];
     371             :       result[i + 2] = p[1];
     372             :       result[i + 3] = p[0];
     373             :     }
     374             : #endif
     375             : 
     376             :   return (sizeof(V) + sizeof(T) + sizeof(int)*2 + sizeof(void*)*5);
     377             : }
     378             : 
     379             : #define fillM(c) do { } while (0)
     380             : #define GHASH(c, result, buf) do_ghash (c->u_mode.gcm.u_ghash_key.key, result, buf)
     381             : 
     382             : #endif /* !GCM_USE_TABLES */
     383             : 
     384             : 
     385             : static unsigned int
     386           0 : ghash_internal (gcry_cipher_hd_t c, byte *result, const byte *buf,
     387             :                 size_t nblocks)
     388             : {
     389           0 :   const unsigned int blocksize = GCRY_GCM_BLOCK_LEN;
     390           0 :   unsigned int burn = 0;
     391             : 
     392           0 :   while (nblocks)
     393             :     {
     394           0 :       burn = GHASH (c, result, buf);
     395           0 :       buf += blocksize;
     396           0 :       nblocks--;
     397             :     }
     398             : 
     399           0 :   return burn + (burn ? 5*sizeof(void*) : 0);
     400             : }
     401             : 
     402             : 
     403             : static void
     404           0 : setupM (gcry_cipher_hd_t c)
     405             : {
     406             : #if defined(GCM_USE_INTEL_PCLMUL) || defined(GCM_USE_ARM_PMULL)
     407           0 :   unsigned int features = _gcry_get_hw_features ();
     408             : #endif
     409             : 
     410             :   if (0)
     411             :     ;
     412             : #ifdef GCM_USE_INTEL_PCLMUL
     413           0 :   else if (features & HWF_INTEL_PCLMUL)
     414             :     {
     415           0 :       c->u_mode.gcm.ghash_fn = _gcry_ghash_intel_pclmul;
     416           0 :       _gcry_ghash_setup_intel_pclmul (c);
     417             :     }
     418             : #endif
     419             : #ifdef GCM_USE_ARM_PMULL
     420             :   else if (features & HWF_ARM_PMULL)
     421             :     {
     422             :       c->u_mode.gcm.ghash_fn = ghash_armv8_ce_pmull;
     423             :       ghash_setup_armv8_ce_pmull (c);
     424             :     }
     425             : #endif
     426             :   else
     427             :     {
     428           0 :       c->u_mode.gcm.ghash_fn = ghash_internal;
     429           0 :       fillM (c);
     430             :     }
     431           0 : }
     432             : 
     433             : 
     434             : static inline void
     435           0 : gcm_bytecounter_add (u32 ctr[2], size_t add)
     436             : {
     437             :   if (sizeof(add) > sizeof(u32))
     438             :     {
     439           0 :       u32 high_add = ((add >> 31) >> 1) & 0xffffffff;
     440           0 :       ctr[1] += high_add;
     441             :     }
     442             : 
     443           0 :   ctr[0] += add;
     444           0 :   if (ctr[0] >= add)
     445           0 :     return;
     446           0 :   ++ctr[1];
     447             : }
     448             : 
     449             : 
     450             : static inline u32
     451           0 : gcm_add32_be128 (byte *ctr, unsigned int add)
     452             : {
     453             :   /* 'ctr' must be aligned to four bytes. */
     454           0 :   const unsigned int blocksize = GCRY_GCM_BLOCK_LEN;
     455           0 :   u32 *pval = (u32 *)(void *)(ctr + blocksize - sizeof(u32));
     456             :   u32 val;
     457             : 
     458           0 :   val = be_bswap32(*pval) + add;
     459           0 :   *pval = be_bswap32(val);
     460             : 
     461           0 :   return val; /* return result as host-endian value */
     462             : }
     463             : 
     464             : 
     465             : static inline int
     466           0 : gcm_check_datalen (u32 ctr[2])
     467             : {
     468             :   /* len(plaintext) <= 2^39-256 bits == 2^36-32 bytes == 2^32-2 blocks */
     469           0 :   if (ctr[1] > 0xfU)
     470           0 :     return 0;
     471           0 :   if (ctr[1] < 0xfU)
     472           0 :     return 1;
     473             : 
     474           0 :   if (ctr[0] <= 0xffffffe0U)
     475           0 :     return 1;
     476             : 
     477           0 :   return 0;
     478             : }
     479             : 
     480             : 
     481             : static inline int
     482           0 : gcm_check_aadlen_or_ivlen (u32 ctr[2])
     483             : {
     484             :   /* len(aad/iv) <= 2^64-1 bits ~= 2^61-1 bytes */
     485           0 :   if (ctr[1] > 0x1fffffffU)
     486           0 :     return 0;
     487           0 :   if (ctr[1] < 0x1fffffffU)
     488           0 :     return 1;
     489             : 
     490             :   if (ctr[0] <= 0xffffffffU)
     491           0 :     return 1;
     492             : 
     493             :   return 0;
     494             : }
     495             : 
     496             : 
     497             : static void
     498           0 : do_ghash_buf(gcry_cipher_hd_t c, byte *hash, const byte *buf,
     499             :              size_t buflen, int do_padding)
     500             : {
     501           0 :   unsigned int blocksize = GCRY_GCM_BLOCK_LEN;
     502           0 :   unsigned int unused = c->u_mode.gcm.mac_unused;
     503           0 :   ghash_fn_t ghash_fn = c->u_mode.gcm.ghash_fn;
     504             :   size_t nblocks, n;
     505           0 :   unsigned int burn = 0;
     506             : 
     507           0 :   if (buflen == 0 && (unused == 0 || !do_padding))
     508           0 :     return;
     509             : 
     510             :   do
     511             :     {
     512           0 :       if (buflen > 0 && (buflen + unused < blocksize || unused > 0))
     513             :         {
     514           0 :           n = blocksize - unused;
     515           0 :           n = n < buflen ? n : buflen;
     516             : 
     517           0 :           buf_cpy (&c->u_mode.gcm.macbuf[unused], buf, n);
     518             : 
     519           0 :           unused += n;
     520           0 :           buf += n;
     521           0 :           buflen -= n;
     522             :         }
     523           0 :       if (!buflen)
     524             :         {
     525           0 :           if (!do_padding)
     526           0 :             break;
     527             : 
     528           0 :           while (unused < blocksize)
     529           0 :             c->u_mode.gcm.macbuf[unused++] = 0;
     530             :         }
     531             : 
     532           0 :       if (unused > 0)
     533             :         {
     534           0 :           gcry_assert (unused == blocksize);
     535             : 
     536             :           /* Process one block from macbuf.  */
     537           0 :           burn = ghash_fn (c, hash, c->u_mode.gcm.macbuf, 1);
     538           0 :           unused = 0;
     539             :         }
     540             : 
     541           0 :       nblocks = buflen / blocksize;
     542             : 
     543           0 :       if (nblocks)
     544             :         {
     545           0 :           burn = ghash_fn (c, hash, buf, nblocks);
     546           0 :           buf += blocksize * nblocks;
     547           0 :           buflen -= blocksize * nblocks;
     548             :         }
     549             :     }
     550           0 :   while (buflen > 0);
     551             : 
     552           0 :   c->u_mode.gcm.mac_unused = unused;
     553             : 
     554           0 :   if (burn)
     555           0 :     _gcry_burn_stack (burn);
     556             : }
     557             : 
     558             : 
     559             : gcry_err_code_t
     560           0 : _gcry_cipher_gcm_encrypt (gcry_cipher_hd_t c,
     561             :                           byte *outbuf, size_t outbuflen,
     562             :                           const byte *inbuf, size_t inbuflen)
     563             : {
     564             :   static const unsigned char zerobuf[MAX_BLOCKSIZE];
     565             :   gcry_err_code_t err;
     566             : 
     567           0 :   if (c->spec->blocksize != GCRY_GCM_BLOCK_LEN)
     568           0 :     return GPG_ERR_CIPHER_ALGO;
     569           0 :   if (outbuflen < inbuflen)
     570           0 :     return GPG_ERR_BUFFER_TOO_SHORT;
     571           0 :   if (c->u_mode.gcm.datalen_over_limits)
     572           0 :     return GPG_ERR_INV_LENGTH;
     573           0 :   if (c->marks.tag
     574           0 :       || c->u_mode.gcm.ghash_data_finalized
     575           0 :       || !c->u_mode.gcm.ghash_fn)
     576           0 :     return GPG_ERR_INV_STATE;
     577             : 
     578           0 :   if (!c->marks.iv)
     579           0 :     _gcry_cipher_gcm_setiv (c, zerobuf, GCRY_GCM_BLOCK_LEN);
     580             : 
     581           0 :   if (c->u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode)
     582           0 :     return GPG_ERR_INV_STATE;
     583             : 
     584           0 :   if (!c->u_mode.gcm.ghash_aad_finalized)
     585             :     {
     586             :       /* Start of encryption marks end of AAD stream. */
     587           0 :       do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, NULL, 0, 1);
     588           0 :       c->u_mode.gcm.ghash_aad_finalized = 1;
     589             :     }
     590             : 
     591           0 :   gcm_bytecounter_add(c->u_mode.gcm.datalen, inbuflen);
     592           0 :   if (!gcm_check_datalen(c->u_mode.gcm.datalen))
     593             :     {
     594           0 :       c->u_mode.gcm.datalen_over_limits = 1;
     595           0 :       return GPG_ERR_INV_LENGTH;
     596             :     }
     597             : 
     598           0 :   err = _gcry_cipher_ctr_encrypt(c, outbuf, outbuflen, inbuf, inbuflen);
     599           0 :   if (err != 0)
     600           0 :     return err;
     601             : 
     602           0 :   do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, outbuf, inbuflen, 0);
     603             : 
     604           0 :   return 0;
     605             : }
     606             : 
     607             : 
     608             : gcry_err_code_t
     609           0 : _gcry_cipher_gcm_decrypt (gcry_cipher_hd_t c,
     610             :                           byte *outbuf, size_t outbuflen,
     611             :                           const byte *inbuf, size_t inbuflen)
     612             : {
     613             :   static const unsigned char zerobuf[MAX_BLOCKSIZE];
     614             : 
     615           0 :   if (c->spec->blocksize != GCRY_GCM_BLOCK_LEN)
     616           0 :     return GPG_ERR_CIPHER_ALGO;
     617           0 :   if (outbuflen < inbuflen)
     618           0 :     return GPG_ERR_BUFFER_TOO_SHORT;
     619           0 :   if (c->u_mode.gcm.datalen_over_limits)
     620           0 :     return GPG_ERR_INV_LENGTH;
     621           0 :   if (c->marks.tag
     622           0 :       || c->u_mode.gcm.ghash_data_finalized
     623           0 :       || !c->u_mode.gcm.ghash_fn)
     624           0 :     return GPG_ERR_INV_STATE;
     625             : 
     626           0 :   if (!c->marks.iv)
     627           0 :     _gcry_cipher_gcm_setiv (c, zerobuf, GCRY_GCM_BLOCK_LEN);
     628             : 
     629           0 :   if (!c->u_mode.gcm.ghash_aad_finalized)
     630             :     {
     631             :       /* Start of decryption marks end of AAD stream. */
     632           0 :       do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, NULL, 0, 1);
     633           0 :       c->u_mode.gcm.ghash_aad_finalized = 1;
     634             :     }
     635             : 
     636           0 :   gcm_bytecounter_add(c->u_mode.gcm.datalen, inbuflen);
     637           0 :   if (!gcm_check_datalen(c->u_mode.gcm.datalen))
     638             :     {
     639           0 :       c->u_mode.gcm.datalen_over_limits = 1;
     640           0 :       return GPG_ERR_INV_LENGTH;
     641             :     }
     642             : 
     643           0 :   do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, inbuf, inbuflen, 0);
     644             : 
     645           0 :   return _gcry_cipher_ctr_encrypt(c, outbuf, outbuflen, inbuf, inbuflen);
     646             : }
     647             : 
     648             : 
     649             : gcry_err_code_t
     650           0 : _gcry_cipher_gcm_authenticate (gcry_cipher_hd_t c,
     651             :                                const byte * aadbuf, size_t aadbuflen)
     652             : {
     653             :   static const unsigned char zerobuf[MAX_BLOCKSIZE];
     654             : 
     655           0 :   if (c->spec->blocksize != GCRY_GCM_BLOCK_LEN)
     656           0 :     return GPG_ERR_CIPHER_ALGO;
     657           0 :   if (c->u_mode.gcm.datalen_over_limits)
     658           0 :     return GPG_ERR_INV_LENGTH;
     659           0 :   if (c->marks.tag
     660           0 :       || c->u_mode.gcm.ghash_aad_finalized
     661           0 :       || c->u_mode.gcm.ghash_data_finalized
     662           0 :       || !c->u_mode.gcm.ghash_fn)
     663           0 :     return GPG_ERR_INV_STATE;
     664             : 
     665           0 :   if (!c->marks.iv)
     666           0 :     _gcry_cipher_gcm_setiv (c, zerobuf, GCRY_GCM_BLOCK_LEN);
     667             : 
     668           0 :   gcm_bytecounter_add(c->u_mode.gcm.aadlen, aadbuflen);
     669           0 :   if (!gcm_check_aadlen_or_ivlen(c->u_mode.gcm.aadlen))
     670             :     {
     671           0 :       c->u_mode.gcm.datalen_over_limits = 1;
     672           0 :       return GPG_ERR_INV_LENGTH;
     673             :     }
     674             : 
     675           0 :   do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, aadbuf, aadbuflen, 0);
     676             : 
     677           0 :   return 0;
     678             : }
     679             : 
     680             : 
     681             : void
     682           0 : _gcry_cipher_gcm_setkey (gcry_cipher_hd_t c)
     683             : {
     684           0 :   memset (c->u_mode.gcm.u_ghash_key.key, 0, GCRY_GCM_BLOCK_LEN);
     685             : 
     686           0 :   c->spec->encrypt (&c->context.c, c->u_mode.gcm.u_ghash_key.key,
     687           0 :                     c->u_mode.gcm.u_ghash_key.key);
     688           0 :   setupM (c);
     689           0 : }
     690             : 
     691             : 
     692             : static gcry_err_code_t
     693           0 : _gcry_cipher_gcm_initiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen)
     694             : {
     695           0 :   memset (c->u_mode.gcm.aadlen, 0, sizeof(c->u_mode.gcm.aadlen));
     696           0 :   memset (c->u_mode.gcm.datalen, 0, sizeof(c->u_mode.gcm.datalen));
     697           0 :   memset (c->u_mode.gcm.u_tag.tag, 0, GCRY_GCM_BLOCK_LEN);
     698           0 :   c->u_mode.gcm.datalen_over_limits = 0;
     699           0 :   c->u_mode.gcm.ghash_data_finalized = 0;
     700           0 :   c->u_mode.gcm.ghash_aad_finalized = 0;
     701             : 
     702           0 :   if (ivlen == 0)
     703           0 :     return GPG_ERR_INV_LENGTH;
     704             : 
     705           0 :   if (ivlen != GCRY_GCM_BLOCK_LEN - 4)
     706             :     {
     707           0 :       u32 iv_bytes[2] = {0, 0};
     708             :       u32 bitlengths[2][2];
     709             : 
     710           0 :       if (!c->u_mode.gcm.ghash_fn)
     711           0 :         return GPG_ERR_INV_STATE;
     712             : 
     713           0 :       memset(c->u_ctr.ctr, 0, GCRY_GCM_BLOCK_LEN);
     714             : 
     715           0 :       gcm_bytecounter_add(iv_bytes, ivlen);
     716           0 :       if (!gcm_check_aadlen_or_ivlen(iv_bytes))
     717             :         {
     718           0 :           c->u_mode.gcm.datalen_over_limits = 1;
     719           0 :           return GPG_ERR_INV_LENGTH;
     720             :         }
     721             : 
     722           0 :       do_ghash_buf(c, c->u_ctr.ctr, iv, ivlen, 1);
     723             : 
     724             :       /* iv length, 64-bit */
     725           0 :       bitlengths[1][1] = be_bswap32(iv_bytes[0] << 3);
     726           0 :       bitlengths[1][0] = be_bswap32((iv_bytes[0] >> 29) |
     727             :                                     (iv_bytes[1] << 3));
     728             :       /* zeros, 64-bit */
     729           0 :       bitlengths[0][1] = 0;
     730           0 :       bitlengths[0][0] = 0;
     731             : 
     732           0 :       do_ghash_buf(c, c->u_ctr.ctr, (byte*)bitlengths, GCRY_GCM_BLOCK_LEN, 1);
     733             : 
     734           0 :       wipememory (iv_bytes, sizeof iv_bytes);
     735           0 :       wipememory (bitlengths, sizeof bitlengths);
     736             :     }
     737             :   else
     738             :     {
     739             :       /* 96-bit IV is handled differently. */
     740           0 :       memcpy (c->u_ctr.ctr, iv, ivlen);
     741           0 :       c->u_ctr.ctr[12] = c->u_ctr.ctr[13] = c->u_ctr.ctr[14] = 0;
     742           0 :       c->u_ctr.ctr[15] = 1;
     743             :     }
     744             : 
     745           0 :   c->spec->encrypt (&c->context.c, c->u_mode.gcm.tagiv, c->u_ctr.ctr);
     746             : 
     747           0 :   gcm_add32_be128 (c->u_ctr.ctr, 1);
     748             : 
     749           0 :   c->unused = 0;
     750           0 :   c->marks.iv = 1;
     751           0 :   c->marks.tag = 0;
     752             : 
     753           0 :   return 0;
     754             : }
     755             : 
     756             : 
     757             : gcry_err_code_t
     758           0 : _gcry_cipher_gcm_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen)
     759             : {
     760           0 :   c->marks.iv = 0;
     761           0 :   c->marks.tag = 0;
     762           0 :   c->u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode = 0;
     763             : 
     764           0 :   if (fips_mode ())
     765             :     {
     766             :       /* Direct invocation of GCM setiv in FIPS mode disables encryption. */
     767           0 :       c->u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode = 1;
     768             :     }
     769             : 
     770           0 :   return _gcry_cipher_gcm_initiv (c, iv, ivlen);
     771             : }
     772             : 
     773             : 
     774             : #if 0 && TODO
     775             : void
     776             : _gcry_cipher_gcm_geniv (gcry_cipher_hd_t c,
     777             :                         byte *ivout, size_t ivoutlen, const byte *nonce,
     778             :                         size_t noncelen)
     779             : {
     780             :   /* nonce:    user provided part (might be null) */
     781             :   /* noncelen: check if proper length (if nonce not null) */
     782             :   /* ivout:    iv used to initialize gcm, output to user */
     783             :   /* ivoutlen: check correct size */
     784             :   byte iv[IVLEN];
     785             : 
     786             :   if (!ivout)
     787             :     return GPG_ERR_INV_ARG;
     788             :   if (ivoutlen != IVLEN)
     789             :     return GPG_ERR_INV_LENGTH;
     790             :   if (nonce != NULL && !is_nonce_ok_len(noncelen))
     791             :     return GPG_ERR_INV_ARG;
     792             : 
     793             :   gcm_generate_iv(iv, nonce, noncelen);
     794             : 
     795             :   c->marks.iv = 0;
     796             :   c->marks.tag = 0;
     797             :   c->u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode = 0;
     798             : 
     799             :   _gcry_cipher_gcm_initiv (c, iv, IVLEN);
     800             : 
     801             :   buf_cpy(ivout, iv, IVLEN);
     802             :   wipememory(iv, sizeof(iv));
     803             : }
     804             : #endif
     805             : 
     806             : 
     807             : static int
     808           0 : is_tag_length_valid(size_t taglen)
     809             : {
     810           0 :   switch (taglen)
     811             :     {
     812             :     /* Allowed tag lengths from NIST SP 800-38D.  */
     813             :     case 128 / 8: /* GCRY_GCM_BLOCK_LEN */
     814             :     case 120 / 8:
     815             :     case 112 / 8:
     816             :     case 104 / 8:
     817             :     case 96 / 8:
     818             :     case 64 / 8:
     819             :     case 32 / 8:
     820           0 :       return 1;
     821             : 
     822             :     default:
     823           0 :       return 0;
     824             :     }
     825             : }
     826             : 
     827             : static gcry_err_code_t
     828           0 : _gcry_cipher_gcm_tag (gcry_cipher_hd_t c,
     829             :                       byte * outbuf, size_t outbuflen, int check)
     830             : {
     831           0 :   if (!(is_tag_length_valid (outbuflen) || outbuflen >= GCRY_GCM_BLOCK_LEN))
     832           0 :     return GPG_ERR_INV_LENGTH;
     833           0 :   if (c->u_mode.gcm.datalen_over_limits)
     834           0 :     return GPG_ERR_INV_LENGTH;
     835             : 
     836           0 :   if (!c->marks.tag)
     837             :     {
     838             :       u32 bitlengths[2][2];
     839             : 
     840           0 :       if (!c->u_mode.gcm.ghash_fn)
     841           0 :         return GPG_ERR_INV_STATE;
     842             : 
     843             :       /* aad length */
     844           0 :       bitlengths[0][1] = be_bswap32(c->u_mode.gcm.aadlen[0] << 3);
     845           0 :       bitlengths[0][0] = be_bswap32((c->u_mode.gcm.aadlen[0] >> 29) |
     846             :                                     (c->u_mode.gcm.aadlen[1] << 3));
     847             :       /* data length */
     848           0 :       bitlengths[1][1] = be_bswap32(c->u_mode.gcm.datalen[0] << 3);
     849           0 :       bitlengths[1][0] = be_bswap32((c->u_mode.gcm.datalen[0] >> 29) |
     850             :                                     (c->u_mode.gcm.datalen[1] << 3));
     851             : 
     852             :       /* Finalize data-stream. */
     853           0 :       do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, NULL, 0, 1);
     854           0 :       c->u_mode.gcm.ghash_aad_finalized = 1;
     855           0 :       c->u_mode.gcm.ghash_data_finalized = 1;
     856             : 
     857             :       /* Add bitlengths to tag. */
     858           0 :       do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, (byte*)bitlengths,
     859             :                    GCRY_GCM_BLOCK_LEN, 1);
     860           0 :       buf_xor (c->u_mode.gcm.u_tag.tag, c->u_mode.gcm.tagiv,
     861           0 :                c->u_mode.gcm.u_tag.tag, GCRY_GCM_BLOCK_LEN);
     862           0 :       c->marks.tag = 1;
     863             : 
     864           0 :       wipememory (bitlengths, sizeof (bitlengths));
     865           0 :       wipememory (c->u_mode.gcm.macbuf, GCRY_GCM_BLOCK_LEN);
     866           0 :       wipememory (c->u_mode.gcm.tagiv, GCRY_GCM_BLOCK_LEN);
     867           0 :       wipememory (c->u_mode.gcm.aadlen, sizeof (c->u_mode.gcm.aadlen));
     868           0 :       wipememory (c->u_mode.gcm.datalen, sizeof (c->u_mode.gcm.datalen));
     869             :     }
     870             : 
     871           0 :   if (!check)
     872             :     {
     873           0 :       if (outbuflen > GCRY_GCM_BLOCK_LEN)
     874           0 :         outbuflen = GCRY_GCM_BLOCK_LEN;
     875             : 
     876             :       /* NB: We already checked that OUTBUF is large enough to hold
     877             :        * the result or has valid truncated length.  */
     878           0 :       memcpy (outbuf, c->u_mode.gcm.u_tag.tag, outbuflen);
     879             :     }
     880             :   else
     881             :     {
     882             :       /* OUTBUFLEN gives the length of the user supplied tag in OUTBUF
     883             :        * and thus we need to compare its length first.  */
     884           0 :       if (!is_tag_length_valid (outbuflen)
     885           0 :           || !buf_eq_const (outbuf, c->u_mode.gcm.u_tag.tag, outbuflen))
     886           0 :         return GPG_ERR_CHECKSUM;
     887             :     }
     888             : 
     889           0 :   return 0;
     890             : }
     891             : 
     892             : 
     893             : gcry_err_code_t
     894           0 : _gcry_cipher_gcm_get_tag (gcry_cipher_hd_t c, unsigned char *outtag,
     895             :                           size_t taglen)
     896             : {
     897             :   /* Outputting authentication tag is part of encryption. */
     898           0 :   if (c->u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode)
     899           0 :     return GPG_ERR_INV_STATE;
     900             : 
     901           0 :   return _gcry_cipher_gcm_tag (c, outtag, taglen, 0);
     902             : }
     903             : 
     904             : gcry_err_code_t
     905           0 : _gcry_cipher_gcm_check_tag (gcry_cipher_hd_t c, const unsigned char *intag,
     906             :                             size_t taglen)
     907             : {
     908           0 :   return _gcry_cipher_gcm_tag (c, (unsigned char *) intag, taglen, 1);
     909             : }

Generated by: LCOV version 1.12