LCOV - code coverage report
Current view: top level - ballet/aes - fd_aes_gcm_ref.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 175 193 90.7 %
Date: 2026-07-23 05:31:48 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     4204405 : #define fd_gcm_init  fd_gcm_init_4bit
       7     4001606 : #define fd_gcm_gmult fd_gcm_gmult_4bit
       8    11136691 : #define fd_gcm_ghash fd_gcm_ghash_4bit
       9             : 
      10             : static void
      11             : fd_aes_gcm_setiv( fd_aes_gcm_ref_t * gcm,
      12     4204405 :                   uchar const        iv[ 12 ] ) {
      13             : 
      14     4204405 :   uint ctr;
      15     4204405 :   gcm->len.u[ 0 ] = 0;  /* AAD length */
      16     4204405 :   gcm->len.u[ 1 ] = 0;  /* Message length */
      17     4204405 :   gcm->ares = 0;
      18     4204405 :   gcm->mres = 0;
      19             : 
      20     4204405 :   memcpy( gcm->Yi.c, iv, 12 );
      21     4204405 :   gcm->Yi.c[12] = 0;
      22     4204405 :   gcm->Yi.c[13] = 0;
      23     4204405 :   gcm->Yi.c[14] = 0;
      24     4204405 :   gcm->Yi.c[15] = 1;
      25     4204405 :   ctr = 1;
      26             : 
      27     4204405 :   gcm->Xi.u[0] = 0;
      28     4204405 :   gcm->Xi.u[1] = 0;
      29             : 
      30     4204405 :   fd_aes_encrypt( gcm->Yi.c, gcm->EK0.c, &gcm->key );
      31     4204405 :   ctr++;
      32             : 
      33     4204405 :   gcm->Yi.d[3] = fd_uint_bswap( ctr );
      34     4204405 : }
      35             : 
      36             : void
      37             : fd_aes_128_gcm_init_ref( fd_aes_gcm_ref_t * gcm,
      38             :                          uchar const        key[ 16 ],
      39     4204405 :                          uchar const        iv[ 12 ] ) {
      40             : 
      41             :   /* TODO: Check key size */
      42             : 
      43     4204405 :   memset( gcm, 0, sizeof(fd_aes_gcm_t) );
      44             : 
      45     4204405 :   fd_aes_key_ref_t * ks = &gcm->key;
      46     4204405 :   fd_aes_set_encrypt_key( key, 128, ks );
      47             : 
      48     4204405 :   fd_aes_encrypt( gcm->H.c, gcm->H.c, ks );
      49     4204405 :   gcm->H.u[ 0 ] = fd_ulong_bswap( gcm->H.u[ 0 ] );
      50     4204405 :   gcm->H.u[ 1 ] = fd_ulong_bswap( gcm->H.u[ 1 ] );
      51             : 
      52     4204405 :   fd_gcm_init( gcm->Htable, gcm->H.u );
      53     4204405 :   fd_aes_gcm_setiv( gcm, iv );
      54     4204405 : }
      55             : 
      56             : static int
      57             : fd_gcm128_aad( fd_aes_gcm_ref_t * aes_gcm,
      58             :                uchar const *      aad,
      59     4204405 :                ulong              aad_sz ) {
      60             : 
      61     4204405 :   ulong alen = aes_gcm->len.u[ 0 ];
      62             : 
      63     4204405 :   if( FD_UNLIKELY( aes_gcm->len.u[ 1 ] ) )
      64           0 :     return -2;
      65             : 
      66     4204405 :   alen += aad_sz;
      67     4204405 :   if (alen > (1UL<<61) || (sizeof(aad_sz) == 8 && alen < aad_sz))
      68           0 :     return -1;
      69     4204405 :   aes_gcm->len.u[0] = alen;
      70             : 
      71     4204405 :   uint n = aes_gcm->ares;
      72     4204405 :   if (n) {
      73           0 :     while (n && aad_sz) {
      74           0 :       aes_gcm->Xi.c[n] ^= *(aad++);
      75           0 :       --aad_sz;
      76           0 :       n = (n + 1) % 16;
      77           0 :     }
      78           0 :     if (n == 0)
      79           0 :       fd_gcm_gmult( aes_gcm->Xi.u, aes_gcm->Htable );
      80           0 :     else {
      81           0 :       aes_gcm->ares = n;
      82           0 :       return 0;
      83           0 :     }
      84           0 :   }
      85     4204405 :   ulong i;
      86     4204405 :   if ((i = (aad_sz & (ulong)-16))) {
      87     4063726 :     fd_gcm_ghash( aes_gcm->Xi.u, aes_gcm->Htable, aad, i );
      88     4063726 :     aad += i;
      89     4063726 :     aad_sz -= i;
      90     4063726 :   }
      91     4204405 :   if (aad_sz) {
      92     4199797 :     n = (unsigned int)aad_sz;
      93    41352721 :     for (i = 0; i < aad_sz; ++i)
      94    37152924 :       aes_gcm->Xi.c[i] ^= aad[i];
      95     4199797 :   }
      96             : 
      97     4204405 :   aes_gcm->ares = n;
      98     4204405 :   return 0;
      99     4204405 : }
     100             : 
     101             : /* TODO separate reference code and GCM128 */
     102             : 
     103             : static int
     104             : fd_gcm128_encrypt( fd_aes_gcm_ref_t * ctx,
     105             :                    uchar const *      in,
     106             :                    uchar *            out,
     107     2097644 :                    ulong              len ) {
     108             : 
     109     2097644 :   uint n, ctr, mres;
     110     2097644 :   ulong i;
     111     2097644 :   ulong mlen = ctx->len.u[1];
     112     2097644 :   void *key = &ctx->key;
     113             : 
     114     2097644 :   mlen += len;
     115     2097644 :   if (mlen > ((1UL<<36) - 32) || (sizeof(len) == 8 && mlen < len))
     116           0 :     return -1;
     117     2097644 :   ctx->len.u[1] = mlen;
     118             : 
     119     2097644 :   mres = ctx->mres;
     120             : 
     121     2097644 :   if (ctx->ares) {
     122             :     /* First call to encrypt finalizes GHASH(AAD) */
     123     2095340 :     if (len == 0) {
     124     2000007 :       fd_gcm_gmult( ctx->Xi.u, ctx->Htable );
     125     2000007 :       ctx->ares = 0;
     126     2000007 :       return 0;
     127     2000007 :     }
     128       95333 :     memcpy(ctx->Xn, ctx->Xi.c, sizeof(ctx->Xi));
     129       95333 :     ctx->Xi.u[0] = 0;
     130       95333 :     ctx->Xi.u[1] = 0;
     131       95333 :     mres = sizeof(ctx->Xi);
     132       95333 :     ctx->ares = 0;
     133       95333 :   }
     134             : 
     135       97637 :   ctr = fd_uint_bswap( ctx->Yi.d[3] );
     136             : 
     137       97637 :   n = mres % 16;
     138    61876396 :   for (i = 0; i < len; ++i) {
     139    61778759 :     if (n == 0) {
     140     3918868 :       fd_aes_encrypt( ctx->Yi.c, ctx->EKi.c, key );
     141     3918868 :       ++ctr;
     142     3918868 :       ctx->Yi.d[3] = fd_uint_bswap( ctr );
     143     3918868 :     }
     144    61778759 :     ctx->Xn[mres++] = out[i] = in[i] ^ ctx->EKi.c[n];
     145    61778759 :     n = (n + 1) % 16;
     146    61778759 :     if (mres == sizeof(ctx->Xn)) {
     147     1258938 :       fd_gcm_ghash( ctx->Xi.u, ctx->Htable, ctx->Xn, sizeof(ctx->Xn) );
     148     1258938 :       mres = 0;
     149     1258938 :     }
     150    61778759 :   }
     151             : 
     152       97637 :   ctx->mres = mres;
     153       97637 :   return 0;
     154     2097644 : }
     155             : 
     156             : static int
     157             : fd_gcm128_decrypt( fd_aes_gcm_ref_t * ctx,
     158             :                    uchar const *      in,
     159             :                    uchar *            out,
     160     2106761 :                    ulong              len ) {
     161             : 
     162     2106761 :   uint n, ctr, mres;
     163     2106761 :   ulong i;
     164     2106761 :   ulong mlen = ctx->len.u[1];
     165     2106761 :   void * key = &ctx->key;
     166             : 
     167     2106761 :   mlen += len;
     168     2106761 :   if (mlen > ((1UL<<36) - 32) || (sizeof(len) == 8 && mlen < len))
     169           0 :     return -1;
     170     2106761 :   ctx->len.u[1] = mlen;
     171             : 
     172     2106761 :   mres = ctx->mres;
     173             : 
     174     2106761 :   if (ctx->ares) {
     175             :     /* First call to decrypt finalizes GHASH(AAD) */
     176     2104457 :     if (len == 0) {
     177     2001599 :       fd_gcm_gmult( ctx->Xi.u, ctx->Htable );
     178     2001599 :       ctx->ares = 0;
     179     2001599 :       return 0;
     180     2001599 :     }
     181      102858 :     memcpy(ctx->Xn, ctx->Xi.c, sizeof(ctx->Xi));
     182      102858 :     ctx->Xi.u[0] = 0;
     183      102858 :     ctx->Xi.u[1] = 0;
     184      102858 :     mres = sizeof(ctx->Xi);
     185      102858 :     ctx->ares = 0;
     186      102858 :   }
     187             : 
     188      105162 :   ctr = fd_uint_bswap( ctx->Yi.d[3] );
     189             : 
     190      105162 :   n = mres % 16;
     191    73402294 :   for (i = 0; i < len; ++i) {
     192    73297132 :     uchar c;
     193    73297132 :     if (n == 0) {
     194     4637434 :       fd_aes_encrypt( ctx->Yi.c, ctx->EKi.c, key );
     195     4637434 :       ++ctr;
     196     4637434 :       ctx->Yi.d[3] = fd_uint_bswap( ctr );
     197     4637434 :     }
     198    73297132 :     out[i] = (ctx->Xn[mres++] = c = in[i]) ^ ctx->EKi.c[n];
     199    73297132 :     n = (n + 1) % 16;
     200    73297132 :     if (mres == sizeof(ctx->Xn)) {
     201     1499289 :       fd_gcm_ghash( ctx->Xi.u, ctx->Htable, ctx->Xn, sizeof(ctx->Xn) );
     202     1499289 :       mres = 0;
     203     1499289 :     }
     204    73297132 :   }
     205             : 
     206      105162 :   ctx->mres = mres;
     207      105162 :   return 0;
     208     2106761 : }
     209             : 
     210             : static void
     211     4204405 : fd_gcm128_finish( fd_aes_gcm_ref_t * ctx ) {
     212             : 
     213     4204405 :   ulong alen = ctx->len.u[0] << 3;  // 176
     214     4204405 :   ulong clen = ctx->len.u[1] << 3;  // 9296
     215             : 
     216     4204405 :   struct {
     217     4204405 :     ulong hi;
     218     4204405 :     ulong lo;
     219     4204405 :   } bitlen;
     220     4204405 :   uint mres = ctx->mres;
     221             : 
     222     4204405 :   if( mres ) {
     223      202335 :     uint blocks = (mres + 15u) & 0xfffffff0u; // 16
     224             : 
     225      202335 :     memset(ctx->Xn + mres, 0, blocks - mres);
     226      202335 :     mres = blocks;
     227      202335 :     if (mres == sizeof(ctx->Xn)) {
     228      110333 :       fd_gcm_ghash( ctx->Xi.u, ctx->Htable, ctx->Xn, mres );
     229      110333 :       mres = 0;
     230      110333 :     }
     231     4002070 :   } else if( ctx->ares ) {
     232           0 :     fd_gcm_gmult( ctx->Xi.u, ctx->Htable );
     233           0 :   }
     234             : 
     235     4204405 :   alen = fd_ulong_bswap( alen );
     236     4204405 :   clen = fd_ulong_bswap( clen );
     237             : 
     238     4204405 :   bitlen.hi = alen;
     239     4204405 :   bitlen.lo = clen;
     240     4204405 :   memcpy( ctx->Xn + mres, &bitlen, sizeof(bitlen) );
     241     4204405 :   mres += (uint)sizeof(bitlen);
     242     4204405 :   fd_gcm_ghash( ctx->Xi.u, ctx->Htable, ctx->Xn, mres );
     243             : 
     244     4204405 :   ctx->Xi.u[0] ^= ctx->EK0.u[0];
     245     4204405 :   ctx->Xi.u[1] ^= ctx->EK0.u[1];
     246     4204405 : }
     247             : 
     248             : void
     249             : fd_aes_gcm_encrypt_ref( fd_aes_gcm_ref_t * aes_gcm,
     250             :                         uchar *            c,
     251             :                         uchar const *      p,
     252             :                         ulong              sz,
     253             :                         uchar const *      aad,
     254             :                         ulong              aad_sz,
     255     2097644 :                         uchar              tag[ 16 ] ) {
     256             : 
     257     2097644 :   fd_gcm128_aad( aes_gcm, aad, aad_sz );
     258             : 
     259     2097644 :   ulong bulk = 0UL;
     260     2097644 :   int res = fd_gcm128_encrypt( aes_gcm, p+bulk, c+bulk, sz-bulk );
     261     2097644 :   FD_DCHECK_CRIT( res==0, "internal error" );
     262             : 
     263             :   /* CRYPTO_gcm128_tag */
     264     2097644 :   fd_gcm128_finish( aes_gcm );
     265     2097644 :   fd_memcpy( tag, aes_gcm->Xi.c, 16 );
     266     2097644 : }
     267             : 
     268             : int
     269             : fd_aes_gcm_decrypt_ref( fd_aes_gcm_ref_t * aes_gcm,
     270             :                         uchar const *      c,
     271             :                         uchar *            p,
     272             :                         ulong              sz,
     273             :                         uchar const *      aad,
     274             :                         ulong              aad_sz,
     275     2106761 :                         uchar const        tag[ 16 ] ) {
     276             : 
     277     2106761 :   fd_gcm128_aad( aes_gcm, aad, aad_sz );
     278             : 
     279     2106761 :   ulong bulk = 0UL;
     280     2106761 :   int res = fd_gcm128_decrypt( aes_gcm, c+bulk, p+bulk, sz-bulk );
     281     2106761 :   FD_DCHECK_CRIT( res==0, "internal error" );
     282             : 
     283             :   /* CRYPTO_gcm128_finish */
     284     2106761 :   fd_gcm128_finish( aes_gcm );
     285     2106761 :   return 0==memcmp( aes_gcm->Xi.c, tag, 16 );  /* TODO USE CONSTANT TIME COMPARE */
     286     2106761 : }

Generated by: LCOV version 1.14