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

Generated by: LCOV version 1.14