LCOV - code coverage report
Current view: top level - ballet/aes - fd_aes_gcm_ref.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 173 191 90.6 %
Date: 2024-11-13 11:58:15 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /* fd_aes_ref.c was imported from the OpenSSL project circa 2023-Aug.
       2             :    Original source files:  crypto/evp/e_aes.c crypto/modes/gcm128.c */
       3             : 
       4             : #include "fd_aes_gcm.h"
       5             : 
       6             : #include <assert.h>
       7             : 
       8     8571387 : #define fd_gcm_init  fd_gcm_init_4bit
       9     4002031 : #define fd_gcm_gmult fd_gcm_gmult_4bit
      10    80108067 : #define fd_gcm_ghash fd_gcm_ghash_4bit
      11             : 
      12             : static void
      13             : fd_aes_gcm_setiv( fd_aes_gcm_ref_t * gcm,
      14     8571387 :                   uchar const        iv[ 12 ] ) {
      15             : 
      16     8571387 :   uint ctr;
      17     8571387 :   gcm->len.u[ 0 ] = 0;  /* AAD length */
      18     8571387 :   gcm->len.u[ 1 ] = 0;  /* Message length */
      19     8571387 :   gcm->ares = 0;
      20     8571387 :   gcm->mres = 0;
      21             : 
      22     8571387 :   memcpy( gcm->Yi.c, iv, 12 );
      23     8571387 :   gcm->Yi.c[12] = 0;
      24     8571387 :   gcm->Yi.c[13] = 0;
      25     8571387 :   gcm->Yi.c[14] = 0;
      26     8571387 :   gcm->Yi.c[15] = 1;
      27     8571387 :   ctr = 1;
      28             : 
      29     8571387 :   gcm->Xi.u[0] = 0;
      30     8571387 :   gcm->Xi.u[1] = 0;
      31             : 
      32     8571387 :   fd_aes_encrypt( gcm->Yi.c, gcm->EK0.c, &gcm->key );
      33     8571387 :   ctr++;
      34             : 
      35     8571387 :   gcm->Yi.d[3] = fd_uint_bswap( ctr );
      36     8571387 : }
      37             : 
      38             : void
      39             : fd_aes_128_gcm_init_ref( fd_aes_gcm_ref_t * gcm,
      40             :                          uchar const        key[ 16 ],
      41     8571387 :                          uchar const        iv[ 12 ] ) {
      42             : 
      43             :   /* TODO: Check key size */
      44             : 
      45     8571387 :   memset( gcm, 0, sizeof(fd_aes_gcm_t) );
      46             : 
      47     8571387 :   fd_aes_key_ref_t * ks = &gcm->key;
      48     8571387 :   fd_aes_set_encrypt_key( key, 128, ks );
      49             : 
      50     8571387 :   fd_aes_encrypt( gcm->H.c, gcm->H.c, ks );
      51     8571387 :   gcm->H.u[ 0 ] = fd_ulong_bswap( gcm->H.u[ 0 ] );
      52     8571387 :   gcm->H.u[ 1 ] = fd_ulong_bswap( gcm->H.u[ 1 ] );
      53             : 
      54     8571387 :   fd_gcm_init( gcm->Htable, gcm->H.u );
      55     8571387 :   fd_aes_gcm_setiv( gcm, iv );
      56     8571387 : }
      57             : 
      58             : static int
      59             : fd_gcm128_aad( fd_aes_gcm_ref_t * aes_gcm,
      60             :                uchar const *      aad,
      61     8571387 :                ulong              aad_sz ) {
      62             : 
      63     8571387 :   ulong alen = aes_gcm->len.u[ 0 ];
      64             : 
      65     8571387 :   if( FD_UNLIKELY( aes_gcm->len.u[ 1 ] ) )
      66           0 :     return -2;
      67             : 
      68     8571387 :   alen += aad_sz;
      69     8571387 :   if (alen > (1UL<<61) || (sizeof(aad_sz) == 8 && alen < aad_sz))
      70           0 :     return -1;
      71     8571387 :   aes_gcm->len.u[0] = alen;
      72             : 
      73     8571387 :   uint n = aes_gcm->ares;
      74     8571387 :   if (n) {
      75           0 :     while (n && aad_sz) {
      76           0 :       aes_gcm->Xi.c[n] ^= *(aad++);
      77           0 :       --aad_sz;
      78           0 :       n = (n + 1) % 16;
      79           0 :     }
      80           0 :     if (n == 0)
      81           0 :       fd_gcm_gmult( aes_gcm->Xi.u, aes_gcm->Htable );
      82           0 :     else {
      83           0 :       aes_gcm->ares = n;
      84           0 :       return 0;
      85           0 :     }
      86           0 :   }
      87     8571387 :   ulong i;
      88     8571387 :   if ((i = (aad_sz & (ulong)-16))) {
      89     6018761 :     fd_gcm_ghash( aes_gcm->Xi.u, aes_gcm->Htable, aad, i );
      90     6018761 :     aad += i;
      91     6018761 :     aad_sz -= i;
      92     6018761 :   }
      93     8571387 :   if (aad_sz) {
      94     8571383 :     n = (unsigned int)aad_sz;
      95    59590975 :     for (i = 0; i < aad_sz; ++i)
      96    51019592 :       aes_gcm->Xi.c[i] ^= aad[i];
      97     8571383 :   }
      98             : 
      99     8571387 :   aes_gcm->ares = n;
     100     8571387 :   return 0;
     101     8571387 : }
     102             : 
     103             : /* TODO separate reference code and GCM128 */
     104             : 
     105             : static int
     106             : fd_gcm128_encrypt( fd_aes_gcm_ref_t * ctx,
     107             :                    uchar const *      in,
     108             :                    uchar *            out,
     109     4416902 :                    ulong              len ) {
     110             : 
     111     4416902 :   uint n, ctr, mres;
     112     4416902 :   ulong i;
     113     4416902 :   ulong mlen = ctx->len.u[1];
     114     4416902 :   void *key = &ctx->key;
     115             : 
     116     4416902 :   mlen += len;
     117     4416902 :   if (mlen > ((1UL<<36) - 32) || (sizeof(len) == 8 && mlen < len))
     118           0 :     return -1;
     119     4416902 :   ctx->len.u[1] = mlen;
     120             : 
     121     4416902 :   mres = ctx->mres;
     122             : 
     123     4416902 :   if (ctx->ares) {
     124             :     /* First call to encrypt finalizes GHASH(AAD) */
     125     4416902 :     if (len == 0) {
     126     2000065 :       fd_gcm_gmult( ctx->Xi.u, ctx->Htable );
     127     2000065 :       ctx->ares = 0;
     128     2000065 :       return 0;
     129     2000065 :     }
     130     2416837 :     memcpy(ctx->Xn, ctx->Xi.c, sizeof(ctx->Xi));
     131     2416837 :     ctx->Xi.u[0] = 0;
     132     2416837 :     ctx->Xi.u[1] = 0;
     133     2416837 :     mres = sizeof(ctx->Xi);
     134     2416837 :     ctx->ares = 0;
     135     2416837 :   }
     136             : 
     137     2416837 :   ctr = fd_uint_bswap( ctx->Yi.d[3] );
     138             : 
     139     2416837 :   n = mres % 16;
     140  1548826860 :   for (i = 0; i < len; ++i) {
     141  1546410023 :     if (n == 0) {
     142    97558602 :       fd_aes_encrypt( ctx->Yi.c, ctx->EKi.c, key );
     143    97558602 :       ++ctr;
     144    97558602 :       ctx->Yi.d[3] = fd_uint_bswap( ctr );
     145    97558602 :     }
     146  1546410023 :     ctx->Xn[mres++] = out[i] = in[i] ^ ctx->EKi.c[n];
     147  1546410023 :     n = (n + 1) % 16;
     148  1546410023 :     if (mres == sizeof(ctx->Xn)) {
     149    31693385 :       fd_gcm_ghash( ctx->Xi.u, ctx->Htable, ctx->Xn, sizeof(ctx->Xn) );
     150    31693385 :       mres = 0;
     151    31693385 :     }
     152  1546410023 :   }
     153             : 
     154     2416837 :   ctx->mres = mres;
     155     2416837 :   return 0;
     156     4416902 : }
     157             : 
     158             : static int
     159             : fd_gcm128_decrypt( fd_aes_gcm_ref_t * ctx,
     160             :                    uchar const *      in,
     161             :                    uchar *            out,
     162     4154485 :                    ulong              len ) {
     163             : 
     164     4154485 :   uint n, ctr, mres;
     165     4154485 :   ulong i;
     166     4154485 :   ulong mlen = ctx->len.u[1];
     167     4154485 :   void * key = &ctx->key;
     168             : 
     169     4154485 :   mlen += len;
     170     4154485 :   if (mlen > ((1UL<<36) - 32) || (sizeof(len) == 8 && mlen < len))
     171           0 :     return -1;
     172     4154485 :   ctx->len.u[1] = mlen;
     173             : 
     174     4154485 :   mres = ctx->mres;
     175             : 
     176     4154485 :   if (ctx->ares) {
     177             :     /* First call to decrypt finalizes GHASH(AAD) */
     178     4154481 :     if (len == 0) {
     179     2001966 :       fd_gcm_gmult( ctx->Xi.u, ctx->Htable );
     180     2001966 :       ctx->ares = 0;
     181     2001966 :       return 0;
     182     2001966 :     }
     183     2152515 :     memcpy(ctx->Xn, ctx->Xi.c, sizeof(ctx->Xi));
     184     2152515 :     ctx->Xi.u[0] = 0;
     185     2152515 :     ctx->Xi.u[1] = 0;
     186     2152515 :     mres = sizeof(ctx->Xi);
     187     2152515 :     ctx->ares = 0;
     188     2152515 :   }
     189             : 
     190     2152519 :   ctr = fd_uint_bswap( ctx->Yi.d[3] );
     191             : 
     192     2152519 :   n = mres % 16;
     193  1583788485 :   for (i = 0; i < len; ++i) {
     194  1581635966 :     uchar c;
     195  1581635966 :     if (n == 0) {
     196    99295343 :       fd_aes_encrypt( ctx->Yi.c, ctx->EKi.c, key );
     197    99295343 :       ++ctr;
     198    99295343 :       ctx->Yi.d[3] = fd_uint_bswap( ctr );
     199    99295343 :     }
     200  1581635966 :     out[i] = (ctx->Xn[mres++] = c = in[i]) ^ ctx->EKi.c[n];
     201  1581635966 :     n = (n + 1) % 16;
     202  1581635966 :     if (mres == sizeof(ctx->Xn)) {
     203    32693714 :       fd_gcm_ghash( ctx->Xi.u, ctx->Htable, ctx->Xn, sizeof(ctx->Xn) );
     204    32693714 :       mres = 0;
     205    32693714 :     }
     206  1581635966 :   }
     207             : 
     208     2152519 :   ctx->mres = mres;
     209     2152519 :   return 0;
     210     4154485 : }
     211             : 
     212             : void
     213     8571387 : fd_gcm128_finish( fd_aes_gcm_ref_t * ctx ) {
     214             : 
     215     8571387 :   ulong alen = ctx->len.u[0] << 3;  // 176
     216     8571387 :   ulong clen = ctx->len.u[1] << 3;  // 9296
     217             : 
     218     8571387 :   struct {
     219     8571387 :     ulong hi;
     220     8571387 :     ulong lo;
     221     8571387 :   } bitlen;
     222     8571387 :   uint mres = ctx->mres;
     223             : 
     224     8571387 :   if( mres ) {
     225     4569158 :     uint blocks = (mres + 15u) & 0xfffffff0u; // 16
     226             : 
     227     4569158 :     memset(ctx->Xn + mres, 0, blocks - mres);
     228     4569158 :     mres = blocks;
     229     4569158 :     if (mres == sizeof(ctx->Xn)) {
     230     1130820 :       fd_gcm_ghash( ctx->Xi.u, ctx->Htable, ctx->Xn, mres );
     231     1130820 :       mres = 0;
     232     1130820 :     }
     233     4569158 :   } else if( ctx->ares ) {
     234           0 :     fd_gcm_gmult( ctx->Xi.u, ctx->Htable );
     235           0 :   }
     236             : 
     237     8571387 :   alen = fd_ulong_bswap( alen );
     238     8571387 :   clen = fd_ulong_bswap( clen );
     239             : 
     240     8571387 :   bitlen.hi = alen;
     241     8571387 :   bitlen.lo = clen;
     242     8571387 :   memcpy( ctx->Xn + mres, &bitlen, sizeof(bitlen) );
     243     8571387 :   mres += (uint)sizeof(bitlen);
     244     8571387 :   fd_gcm_ghash( ctx->Xi.u, ctx->Htable, ctx->Xn, mres );
     245             : 
     246     8571387 :   ctx->Xi.u[0] ^= ctx->EK0.u[0];
     247     8571387 :   ctx->Xi.u[1] ^= ctx->EK0.u[1];
     248     8571387 : }
     249             : 
     250             : void
     251             : fd_aes_gcm_encrypt_ref( fd_aes_gcm_ref_t * aes_gcm,
     252             :                         uchar *            c,
     253             :                         uchar const *      p,
     254             :                         ulong              sz,
     255             :                         uchar const *      aad,
     256             :                         ulong              aad_sz,
     257     4416902 :                         uchar              tag[ 16 ] ) {
     258             : 
     259     4416902 :   fd_gcm128_aad( aes_gcm, aad, aad_sz );
     260             : 
     261     4416902 :   ulong bulk = 0UL;
     262     4416902 :   assert( 0==fd_gcm128_encrypt( aes_gcm, p+bulk, c+bulk, sz-bulk ) );
     263             : 
     264             :   /* CRYPTO_gcm128_tag */
     265     4416902 :   fd_gcm128_finish( aes_gcm );
     266     4416902 :   fd_memcpy( tag, aes_gcm->Xi.c, 16 );
     267     4416902 : }
     268             : 
     269             : int
     270             : fd_aes_gcm_decrypt_ref( fd_aes_gcm_ref_t * aes_gcm,
     271             :                         uchar const *      c,
     272             :                         uchar *            p,
     273             :                         ulong              sz,
     274             :                         uchar const *      aad,
     275             :                         ulong              aad_sz,
     276     4154485 :                         uchar const        tag[ 16 ] ) {
     277             : 
     278     4154485 :   fd_gcm128_aad( aes_gcm, aad, aad_sz );
     279             : 
     280     4154485 :   ulong bulk = 0UL;
     281     4154485 :   assert( 0==fd_gcm128_decrypt( aes_gcm, c+bulk, p+bulk, sz-bulk ) );
     282             : 
     283             :   /* CRYPTO_gcm128_finish */
     284     4154485 :   fd_gcm128_finish( aes_gcm );
     285     4154485 :   return 0==memcmp( aes_gcm->Xi.c, tag, 16 );  /* TODO USE CONSTANT TIME COMPARE */
     286     4154485 : }

Generated by: LCOV version 1.14