LCOV - code coverage report
Current view: top level - openssh-6.6p1 - umac.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 299 326 91.7 %
Date: 2014-08-01 Functions: 24 24 100.0 %
Branches: 65 86 75.6 %

           Branch data     Line data    Source code
       1                 :            : /* $OpenBSD: umac.c,v 1.8 2013/11/08 00:39:15 djm Exp $ */
       2                 :            : /* -----------------------------------------------------------------------
       3                 :            :  * 
       4                 :            :  * umac.c -- C Implementation UMAC Message Authentication
       5                 :            :  *
       6                 :            :  * Version 0.93b of rfc4418.txt -- 2006 July 18
       7                 :            :  *
       8                 :            :  * For a full description of UMAC message authentication see the UMAC
       9                 :            :  * world-wide-web page at http://www.cs.ucdavis.edu/~rogaway/umac
      10                 :            :  * Please report bugs and suggestions to the UMAC webpage.
      11                 :            :  *
      12                 :            :  * Copyright (c) 1999-2006 Ted Krovetz
      13                 :            :  *                                                                 
      14                 :            :  * Permission to use, copy, modify, and distribute this software and
      15                 :            :  * its documentation for any purpose and with or without fee, is hereby
      16                 :            :  * granted provided that the above copyright notice appears in all copies
      17                 :            :  * and in supporting documentation, and that the name of the copyright
      18                 :            :  * holder not be used in advertising or publicity pertaining to
      19                 :            :  * distribution of the software without specific, written prior permission.
      20                 :            :  *
      21                 :            :  * Comments should be directed to Ted Krovetz (tdk@acm.org)                                        
      22                 :            :  *                                                                   
      23                 :            :  * ---------------------------------------------------------------------- */
      24                 :            :  
      25                 :            :  /* ////////////////////// IMPORTANT NOTES /////////////////////////////////
      26                 :            :   *
      27                 :            :   * 1) This version does not work properly on messages larger than 16MB
      28                 :            :   *
      29                 :            :   * 2) If you set the switch to use SSE2, then all data must be 16-byte
      30                 :            :   *    aligned
      31                 :            :   *
      32                 :            :   * 3) When calling the function umac(), it is assumed that msg is in
      33                 :            :   * a writable buffer of length divisible by 32 bytes. The message itself
      34                 :            :   * does not have to fill the entire buffer, but bytes beyond msg may be
      35                 :            :   * zeroed.
      36                 :            :   *
      37                 :            :   * 4) Three free AES implementations are supported by this implementation of
      38                 :            :   * UMAC. Paulo Barreto's version is in the public domain and can be found
      39                 :            :   * at http://www.esat.kuleuven.ac.be/~rijmen/rijndael/ (search for
      40                 :            :   * "Barreto"). The only two files needed are rijndael-alg-fst.c and
      41                 :            :   * rijndael-alg-fst.h. Brian Gladman's version is distributed with the GNU
      42                 :            :   * Public lisence at http://fp.gladman.plus.com/AES/index.htm. It
      43                 :            :   * includes a fast IA-32 assembly version. The OpenSSL crypo library is
      44                 :            :   * the third.
      45                 :            :   *
      46                 :            :   * 5) With FORCE_C_ONLY flags set to 0, incorrect results are sometimes
      47                 :            :   * produced under gcc with optimizations set -O3 or higher. Dunno why.
      48                 :            :   *
      49                 :            :   /////////////////////////////////////////////////////////////////////// */
      50                 :            :  
      51                 :            : /* ---------------------------------------------------------------------- */
      52                 :            : /* --- User Switches ---------------------------------------------------- */
      53                 :            : /* ---------------------------------------------------------------------- */
      54                 :            : 
      55                 :            : #ifndef UMAC_OUTPUT_LEN
      56                 :            : #define UMAC_OUTPUT_LEN     8  /* Alowable: 4, 8, 12, 16                  */
      57                 :            : #endif
      58                 :            : 
      59                 :            : #if UMAC_OUTPUT_LEN != 4 && UMAC_OUTPUT_LEN != 8 && \
      60                 :            :     UMAC_OUTPUT_LEN != 12 && UMAC_OUTPUT_LEN != 16
      61                 :            : # error UMAC_OUTPUT_LEN must be defined to 4, 8, 12 or 16
      62                 :            : #endif
      63                 :            : 
      64                 :            : /* #define FORCE_C_ONLY        1  ANSI C and 64-bit integers req'd        */
      65                 :            : /* #define AES_IMPLEMENTAION   1  1 = OpenSSL, 2 = Barreto, 3 = Gladman   */
      66                 :            : /* #define SSE2                0  Is SSE2 is available?                   */
      67                 :            : /* #define RUN_TESTS           0  Run basic correctness/speed tests       */
      68                 :            : /* #define UMAC_AE_SUPPORT     0  Enable auhthenticated encrytion         */
      69                 :            : 
      70                 :            : /* ---------------------------------------------------------------------- */
      71                 :            : /* -- Global Includes --------------------------------------------------- */
      72                 :            : /* ---------------------------------------------------------------------- */
      73                 :            : 
      74                 :            : #include "includes.h"
      75                 :            : #include <sys/types.h>
      76                 :            : 
      77                 :            : #include "xmalloc.h"
      78                 :            : #include "umac.h"
      79                 :            : #include <string.h>
      80                 :            : #include <stdlib.h>
      81                 :            : #include <stddef.h>
      82                 :            : 
      83                 :            : /* ---------------------------------------------------------------------- */
      84                 :            : /* --- Primitive Data Types ---                                           */
      85                 :            : /* ---------------------------------------------------------------------- */
      86                 :            : 
      87                 :            : /* The following assumptions may need change on your system */
      88                 :            : typedef u_int8_t        UINT8;  /* 1 byte   */
      89                 :            : typedef u_int16_t       UINT16; /* 2 byte   */
      90                 :            : typedef u_int32_t       UINT32; /* 4 byte   */
      91                 :            : typedef u_int64_t       UINT64; /* 8 bytes  */
      92                 :            : typedef unsigned int    UWORD;  /* Register */
      93                 :            : 
      94                 :            : /* ---------------------------------------------------------------------- */
      95                 :            : /* --- Constants -------------------------------------------------------- */
      96                 :            : /* ---------------------------------------------------------------------- */
      97                 :            : 
      98                 :            : #define UMAC_KEY_LEN           16  /* UMAC takes 16 bytes of external key */
      99                 :            : 
     100                 :            : /* Message "words" are read from memory in an endian-specific manner.     */
     101                 :            : /* For this implementation to behave correctly, __LITTLE_ENDIAN__ must    */
     102                 :            : /* be set true if the host computer is little-endian.                     */
     103                 :            : 
     104                 :            : #if BYTE_ORDER == LITTLE_ENDIAN
     105                 :            : #define __LITTLE_ENDIAN__ 1
     106                 :            : #else
     107                 :            : #define __LITTLE_ENDIAN__ 0
     108                 :            : #endif
     109                 :            : 
     110                 :            : /* ---------------------------------------------------------------------- */
     111                 :            : /* ---------------------------------------------------------------------- */
     112                 :            : /* ----- Architecture Specific ------------------------------------------ */
     113                 :            : /* ---------------------------------------------------------------------- */
     114                 :            : /* ---------------------------------------------------------------------- */
     115                 :            : 
     116                 :            : 
     117                 :            : /* ---------------------------------------------------------------------- */
     118                 :            : /* ---------------------------------------------------------------------- */
     119                 :            : /* ----- Primitive Routines --------------------------------------------- */
     120                 :            : /* ---------------------------------------------------------------------- */
     121                 :            : /* ---------------------------------------------------------------------- */
     122                 :            : 
     123                 :            : 
     124                 :            : /* ---------------------------------------------------------------------- */
     125                 :            : /* --- 32-bit by 32-bit to 64-bit Multiplication ------------------------ */
     126                 :            : /* ---------------------------------------------------------------------- */
     127                 :            : 
     128                 :            : #define MUL64(a,b) ((UINT64)((UINT64)(UINT32)(a) * (UINT64)(UINT32)(b)))
     129                 :            : 
     130                 :            : /* ---------------------------------------------------------------------- */
     131                 :            : /* --- Endian Conversion --- Forcing assembly on some platforms           */
     132                 :            : /* ---------------------------------------------------------------------- */
     133                 :            : 
     134                 :            : #if HAVE_SWAP32
     135                 :            : #define LOAD_UINT32_REVERSED(p)         (swap32(*(const UINT32 *)(p)))
     136                 :            : #define STORE_UINT32_REVERSED(p,v)      (*(UINT32 *)(p) = swap32(v))
     137                 :            : #else /* HAVE_SWAP32 */
     138                 :            : 
     139                 :            : static UINT32 LOAD_UINT32_REVERSED(const void *ptr)
     140                 :            : {
     141                 :     113244 :     UINT32 temp = *(const UINT32 *)ptr;
     142                 :     226488 :     temp = (temp >> 24) | ((temp & 0x00FF0000) >> 8 )
     143                 :     113244 :          | ((temp & 0x0000FF00) << 8 ) | (temp << 24);
     144                 :            :     return (UINT32)temp;
     145                 :            : }
     146                 :            : 
     147                 :            : # if (__LITTLE_ENDIAN__)
     148                 :            : static void STORE_UINT32_REVERSED(void *ptr, UINT32 x)
     149                 :            : {
     150                 :       6400 :     UINT32 i = (UINT32)x;
     151                 :      12800 :     *(UINT32 *)ptr = (i >> 24) | ((i & 0x00FF0000) >> 8 )
     152                 :       6400 :                    | ((i & 0x0000FF00) << 8 ) | (i << 24);
     153                 :            : }
     154                 :            : # endif /* __LITTLE_ENDIAN */
     155                 :            : #endif /* HAVE_SWAP32 */
     156                 :            : 
     157                 :            : /* The following definitions use the above reversal-primitives to do the right
     158                 :            :  * thing on endian specific load and stores.
     159                 :            :  */
     160                 :            : 
     161                 :            : #if (__LITTLE_ENDIAN__)
     162                 :            : #define LOAD_UINT32_LITTLE(ptr)     (*(const UINT32 *)(ptr))
     163                 :            : #define STORE_UINT32_BIG(ptr,x)     STORE_UINT32_REVERSED(ptr,x)
     164                 :            : #else
     165                 :            : #define LOAD_UINT32_LITTLE(ptr)     LOAD_UINT32_REVERSED(ptr)
     166                 :            : #define STORE_UINT32_BIG(ptr,x)     (*(UINT32 *)(ptr) = (UINT32)(x))
     167                 :            : #endif
     168                 :            : 
     169                 :            : /* ---------------------------------------------------------------------- */
     170                 :            : /* ---------------------------------------------------------------------- */
     171                 :            : /* ----- Begin KDF & PDF Section ---------------------------------------- */
     172                 :            : /* ---------------------------------------------------------------------- */
     173                 :            : /* ---------------------------------------------------------------------- */
     174                 :            : 
     175                 :            : /* UMAC uses AES with 16 byte block and key lengths */
     176                 :            : #define AES_BLOCK_LEN  16
     177                 :            : 
     178                 :            : /* OpenSSL's AES */
     179                 :            : #include "openbsd-compat/openssl-compat.h"
     180                 :            : #ifndef USE_BUILTIN_RIJNDAEL
     181                 :            : # include <openssl/aes.h>
     182                 :            : #endif
     183                 :            : typedef AES_KEY aes_int_key[1];
     184                 :            : #define aes_encryption(in,out,int_key)                  \
     185                 :            :   AES_encrypt((u_char *)(in),(u_char *)(out),(AES_KEY *)int_key)
     186                 :            : #define aes_key_setup(key,int_key)                      \
     187                 :            :   AES_set_encrypt_key((const u_char *)(key),UMAC_KEY_LEN*8,int_key)
     188                 :            : 
     189                 :            : /* The user-supplied UMAC key is stretched using AES in a counter
     190                 :            :  * mode to supply all random bits needed by UMAC. The kdf function takes
     191                 :            :  * an AES internal key representation 'key' and writes a stream of
     192                 :            :  * 'nbytes' bytes to the memory pointed at by 'bufp'. Each distinct
     193                 :            :  * 'ndx' causes a distinct byte stream.
     194                 :            :  */
     195                 :       1910 : static void kdf(void *bufp, aes_int_key key, UINT8 ndx, int nbytes)
     196                 :            : {
     197                 :       1910 :     UINT8 in_buf[AES_BLOCK_LEN] = {0};
     198                 :            :     UINT8 out_buf[AES_BLOCK_LEN];
     199                 :       1910 :     UINT8 *dst_buf = (UINT8 *)bufp;
     200                 :            :     int i;
     201                 :            :     
     202                 :            :     /* Setup the initial value */
     203                 :       1910 :     in_buf[AES_BLOCK_LEN-9] = ndx;
     204                 :       1910 :     in_buf[AES_BLOCK_LEN-1] = i = 1;
     205                 :            :         
     206         [ +  + ]:      38258 :     while (nbytes >= AES_BLOCK_LEN) {
     207                 :      36348 :         aes_encryption(in_buf, out_buf, key);
     208                 :            :         memcpy(dst_buf,out_buf,AES_BLOCK_LEN);
     209                 :      36348 :         in_buf[AES_BLOCK_LEN-1] = ++i;
     210                 :      36348 :         nbytes -= AES_BLOCK_LEN;
     211                 :      36348 :         dst_buf += AES_BLOCK_LEN;
     212                 :            :     }
     213         [ +  + ]:       1910 :     if (nbytes) {
     214                 :        198 :         aes_encryption(in_buf, out_buf, key);
     215                 :        198 :         memcpy(dst_buf,out_buf,nbytes);
     216                 :            :     }
     217                 :       1910 : }
     218                 :            : 
     219                 :            : /* The final UHASH result is XOR'd with the output of a pseudorandom
     220                 :            :  * function. Here, we use AES to generate random output and 
     221                 :            :  * xor the appropriate bytes depending on the last bits of nonce.
     222                 :            :  * This scheme is optimized for sequential, increasing big-endian nonces.
     223                 :            :  */
     224                 :            : 
     225                 :            : typedef struct {
     226                 :            :     UINT8 cache[AES_BLOCK_LEN];  /* Previous AES output is saved      */
     227                 :            :     UINT8 nonce[AES_BLOCK_LEN];  /* The AES input making above cache  */
     228                 :            :     aes_int_key prf_key;         /* Expanded AES key for PDF          */
     229                 :            : } pdf_ctx;
     230                 :            : 
     231                 :        382 : static void pdf_init(pdf_ctx *pc, aes_int_key prf_key)
     232                 :            : {
     233                 :            :     UINT8 buf[UMAC_KEY_LEN];
     234                 :            :     
     235                 :        382 :     kdf(buf, prf_key, 0, UMAC_KEY_LEN);
     236                 :        382 :     aes_key_setup(buf, pc->prf_key);
     237                 :            :     
     238                 :            :     /* Initialize pdf and cache */
     239                 :        382 :     memset(pc->nonce, 0, sizeof(pc->nonce));
     240                 :        382 :     aes_encryption(pc->nonce, pc->cache, pc->prf_key);
     241                 :        382 : }
     242                 :            : 
     243                 :       2152 : static void pdf_gen_xor(pdf_ctx *pc, const UINT8 nonce[8], UINT8 buf[8])
     244                 :            : {
     245                 :            :     /* 'ndx' indicates that we'll be using the 0th or 1st eight bytes
     246                 :            :      * of the AES output. If last time around we returned the ndx-1st
     247                 :            :      * element, then we may have the result in the cache already.
     248                 :            :      */
     249                 :            :      
     250                 :            : #if (UMAC_OUTPUT_LEN == 4)
     251                 :            : #define LOW_BIT_MASK 3
     252                 :            : #elif (UMAC_OUTPUT_LEN == 8)
     253                 :            : #define LOW_BIT_MASK 1
     254                 :            : #elif (UMAC_OUTPUT_LEN > 8)
     255                 :            : #define LOW_BIT_MASK 0
     256                 :            : #endif
     257                 :            :     union {
     258                 :            :         UINT8 tmp_nonce_lo[4];
     259                 :            :         UINT32 align;
     260                 :            :     } t;
     261                 :            : #if LOW_BIT_MASK != 0
     262                 :       1104 :     int ndx = nonce[7] & LOW_BIT_MASK;
     263                 :            : #endif
     264                 :       2152 :     *(UINT32 *)t.tmp_nonce_lo = ((const UINT32 *)nonce)[1];
     265                 :       1104 :     t.tmp_nonce_lo[3] &= ~LOW_BIT_MASK; /* zero last bit */
     266                 :            :     
     267 [ +  + ][ -  + ]:       2152 :     if ( (((UINT32 *)t.tmp_nonce_lo)[0] != ((UINT32 *)pc->nonce)[1]) ||
     268                 :        416 :          (((const UINT32 *)nonce)[0] != ((UINT32 *)pc->nonce)[0]) )
     269                 :            :     {
     270                 :       1736 :         ((UINT32 *)pc->nonce)[0] = ((const UINT32 *)nonce)[0];
     271                 :       1736 :         ((UINT32 *)pc->nonce)[1] = ((UINT32 *)t.tmp_nonce_lo)[0];
     272                 :       1736 :         aes_encryption(pc->nonce, pc->cache, pc->prf_key);
     273                 :            :     }
     274                 :            :     
     275                 :            : #if (UMAC_OUTPUT_LEN == 4)
     276                 :            :     *((UINT32 *)buf) ^= ((UINT32 *)pc->cache)[ndx];
     277                 :            : #elif (UMAC_OUTPUT_LEN == 8)
     278                 :       1104 :     *((UINT64 *)buf) ^= ((UINT64 *)pc->cache)[ndx];
     279                 :            : #elif (UMAC_OUTPUT_LEN == 12)
     280                 :            :     ((UINT64 *)buf)[0] ^= ((UINT64 *)pc->cache)[0];
     281                 :            :     ((UINT32 *)buf)[2] ^= ((UINT32 *)pc->cache)[2];
     282                 :            : #elif (UMAC_OUTPUT_LEN == 16)
     283                 :       1048 :     ((UINT64 *)buf)[0] ^= ((UINT64 *)pc->cache)[0];
     284                 :       1048 :     ((UINT64 *)buf)[1] ^= ((UINT64 *)pc->cache)[1];
     285                 :            : #endif
     286                 :       2152 : }
     287                 :            : 
     288                 :            : /* ---------------------------------------------------------------------- */
     289                 :            : /* ---------------------------------------------------------------------- */
     290                 :            : /* ----- Begin NH Hash Section ------------------------------------------ */
     291                 :            : /* ---------------------------------------------------------------------- */
     292                 :            : /* ---------------------------------------------------------------------- */
     293                 :            : 
     294                 :            : /* The NH-based hash functions used in UMAC are described in the UMAC paper
     295                 :            :  * and specification, both of which can be found at the UMAC website.     
     296                 :            :  * The interface to this implementation has two         
     297                 :            :  * versions, one expects the entire message being hashed to be passed
     298                 :            :  * in a single buffer and returns the hash result immediately. The second
     299                 :            :  * allows the message to be passed in a sequence of buffers. In the          
     300                 :            :  * muliple-buffer interface, the client calls the routine nh_update() as     
     301                 :            :  * many times as necessary. When there is no more data to be fed to the   
     302                 :            :  * hash, the client calls nh_final() which calculates the hash output.    
     303                 :            :  * Before beginning another hash calculation the nh_reset() routine       
     304                 :            :  * must be called. The single-buffer routine, nh(), is equivalent to  
     305                 :            :  * the sequence of calls nh_update() and nh_final(); however it is        
     306                 :            :  * optimized and should be prefered whenever the multiple-buffer interface
     307                 :            :  * is not necessary. When using either interface, it is the client's         
     308                 :            :  * responsability to pass no more than L1_KEY_LEN bytes per hash result.            
     309                 :            :  *                                                                        
     310                 :            :  * The routine nh_init() initializes the nh_ctx data structure and        
     311                 :            :  * must be called once, before any other PDF routine.                     
     312                 :            :  */
     313                 :            :  
     314                 :            :  /* The "nh_aux" routines do the actual NH hashing work. They
     315                 :            :   * expect buffers to be multiples of L1_PAD_BOUNDARY. These routines
     316                 :            :   * produce output for all STREAMS NH iterations in one call, 
     317                 :            :   * allowing the parallel implementation of the streams.
     318                 :            :   */
     319                 :            : 
     320                 :            : #define STREAMS (UMAC_OUTPUT_LEN / 4) /* Number of times hash is applied  */
     321                 :            : #define L1_KEY_LEN         1024     /* Internal key bytes                 */
     322                 :            : #define L1_KEY_SHIFT         16     /* Toeplitz key shift between streams */
     323                 :            : #define L1_PAD_BOUNDARY      32     /* pad message to boundary multiple   */
     324                 :            : #define ALLOC_BOUNDARY       16     /* Keep buffers aligned to this       */
     325                 :            : #define HASH_BUF_BYTES       64     /* nh_aux_hb buffer multiple          */
     326                 :            : 
     327                 :            : typedef struct {
     328                 :            :     UINT8  nh_key [L1_KEY_LEN + L1_KEY_SHIFT * (STREAMS - 1)]; /* NH Key */
     329                 :            :     UINT8  data   [HASH_BUF_BYTES];    /* Incoming data buffer           */
     330                 :            :     int next_data_empty;    /* Bookeeping variable for data buffer.       */
     331                 :            :     int bytes_hashed;        /* Bytes (out of L1_KEY_LEN) incorperated.   */
     332                 :            :     UINT64 state[STREAMS];               /* on-line state     */
     333                 :            : } nh_ctx;
     334                 :            : 
     335                 :            : 
     336                 :            : #if (UMAC_OUTPUT_LEN == 4)
     337                 :            : 
     338                 :            : static void nh_aux(void *kp, const void *dp, void *hp, UINT32 dlen)
     339                 :            : /* NH hashing primitive. Previous (partial) hash result is loaded and     
     340                 :            : * then stored via hp pointer. The length of the data pointed at by "dp",
     341                 :            : * "dlen", is guaranteed to be divisible by L1_PAD_BOUNDARY (32).  Key
     342                 :            : * is expected to be endian compensated in memory at key setup.    
     343                 :            : */
     344                 :            : {
     345                 :            :     UINT64 h;
     346                 :            :     UWORD c = dlen / 32;
     347                 :            :     UINT32 *k = (UINT32 *)kp;
     348                 :            :     const UINT32 *d = (const UINT32 *)dp;
     349                 :            :     UINT32 d0,d1,d2,d3,d4,d5,d6,d7;
     350                 :            :     UINT32 k0,k1,k2,k3,k4,k5,k6,k7;
     351                 :            :     
     352                 :            :     h = *((UINT64 *)hp);
     353                 :            :     do {
     354                 :            :         d0 = LOAD_UINT32_LITTLE(d+0); d1 = LOAD_UINT32_LITTLE(d+1);
     355                 :            :         d2 = LOAD_UINT32_LITTLE(d+2); d3 = LOAD_UINT32_LITTLE(d+3);
     356                 :            :         d4 = LOAD_UINT32_LITTLE(d+4); d5 = LOAD_UINT32_LITTLE(d+5);
     357                 :            :         d6 = LOAD_UINT32_LITTLE(d+6); d7 = LOAD_UINT32_LITTLE(d+7);
     358                 :            :         k0 = *(k+0); k1 = *(k+1); k2 = *(k+2); k3 = *(k+3);
     359                 :            :         k4 = *(k+4); k5 = *(k+5); k6 = *(k+6); k7 = *(k+7);
     360                 :            :         h += MUL64((k0 + d0), (k4 + d4));
     361                 :            :         h += MUL64((k1 + d1), (k5 + d5));
     362                 :            :         h += MUL64((k2 + d2), (k6 + d6));
     363                 :            :         h += MUL64((k3 + d3), (k7 + d7));
     364                 :            :         
     365                 :            :         d += 8;
     366                 :            :         k += 8;
     367                 :            :     } while (--c);
     368                 :            :   *((UINT64 *)hp) = h;
     369                 :            : }
     370                 :            : 
     371                 :            : #elif (UMAC_OUTPUT_LEN == 8)
     372                 :            : 
     373                 :       3644 : static void nh_aux(void *kp, const void *dp, void *hp, UINT32 dlen)
     374                 :            : /* Same as previous nh_aux, but two streams are handled in one pass,
     375                 :            :  * reading and writing 16 bytes of hash-state per call.
     376                 :            :  */
     377                 :            : {
     378                 :            :   UINT64 h1,h2;
     379                 :       3644 :   UWORD c = dlen / 32;
     380                 :       3644 :   UINT32 *k = (UINT32 *)kp;
     381                 :       3644 :   const UINT32 *d = (const UINT32 *)dp;
     382                 :            :   UINT32 d0,d1,d2,d3,d4,d5,d6,d7;
     383                 :            :   UINT32 k0,k1,k2,k3,k4,k5,k6,k7,
     384                 :            :         k8,k9,k10,k11;
     385                 :            : 
     386                 :       3644 :   h1 = *((UINT64 *)hp);
     387                 :       3644 :   h2 = *((UINT64 *)hp + 1);
     388                 :       3644 :   k0 = *(k+0); k1 = *(k+1); k2 = *(k+2); k3 = *(k+3);
     389                 :            :   do {
     390                 :      78095 :     d0 = LOAD_UINT32_LITTLE(d+0); d1 = LOAD_UINT32_LITTLE(d+1);
     391                 :      78095 :     d2 = LOAD_UINT32_LITTLE(d+2); d3 = LOAD_UINT32_LITTLE(d+3);
     392                 :      78095 :     d4 = LOAD_UINT32_LITTLE(d+4); d5 = LOAD_UINT32_LITTLE(d+5);
     393                 :      78095 :     d6 = LOAD_UINT32_LITTLE(d+6); d7 = LOAD_UINT32_LITTLE(d+7);
     394                 :      78095 :     k4 = *(k+4); k5 = *(k+5); k6 = *(k+6); k7 = *(k+7);
     395                 :      78095 :     k8 = *(k+8); k9 = *(k+9); k10 = *(k+10); k11 = *(k+11);
     396                 :            : 
     397                 :      78095 :     h1 += MUL64((k0 + d0), (k4 + d4));
     398                 :      78095 :     h2 += MUL64((k4 + d0), (k8 + d4));
     399                 :            : 
     400                 :      78095 :     h1 += MUL64((k1 + d1), (k5 + d5));
     401                 :      78095 :     h2 += MUL64((k5 + d1), (k9 + d5));
     402                 :            : 
     403                 :      78095 :     h1 += MUL64((k2 + d2), (k6 + d6));
     404                 :      78095 :     h2 += MUL64((k6 + d2), (k10 + d6));
     405                 :            : 
     406                 :      78095 :     h1 += MUL64((k3 + d3), (k7 + d7));
     407                 :      78095 :     h2 += MUL64((k7 + d3), (k11 + d7));
     408                 :            : 
     409                 :      78095 :     k0 = k8; k1 = k9; k2 = k10; k3 = k11;
     410                 :            : 
     411                 :      78095 :     d += 8;
     412                 :      78095 :     k += 8;
     413         [ +  + ]:      78095 :   } while (--c);
     414                 :       3644 :   ((UINT64 *)hp)[0] = h1;
     415                 :       3644 :   ((UINT64 *)hp)[1] = h2;
     416                 :       3644 : }
     417                 :            : 
     418                 :            : #elif (UMAC_OUTPUT_LEN == 12)
     419                 :            : 
     420                 :            : static void nh_aux(void *kp, const void *dp, void *hp, UINT32 dlen)
     421                 :            : /* Same as previous nh_aux, but two streams are handled in one pass,
     422                 :            :  * reading and writing 24 bytes of hash-state per call.
     423                 :            : */
     424                 :            : {
     425                 :            :     UINT64 h1,h2,h3;
     426                 :            :     UWORD c = dlen / 32;
     427                 :            :     UINT32 *k = (UINT32 *)kp;
     428                 :            :     const UINT32 *d = (const UINT32 *)dp;
     429                 :            :     UINT32 d0,d1,d2,d3,d4,d5,d6,d7;
     430                 :            :     UINT32 k0,k1,k2,k3,k4,k5,k6,k7,
     431                 :            :         k8,k9,k10,k11,k12,k13,k14,k15;
     432                 :            :     
     433                 :            :     h1 = *((UINT64 *)hp);
     434                 :            :     h2 = *((UINT64 *)hp + 1);
     435                 :            :     h3 = *((UINT64 *)hp + 2);
     436                 :            :     k0 = *(k+0); k1 = *(k+1); k2 = *(k+2); k3 = *(k+3);
     437                 :            :     k4 = *(k+4); k5 = *(k+5); k6 = *(k+6); k7 = *(k+7);
     438                 :            :     do {
     439                 :            :         d0 = LOAD_UINT32_LITTLE(d+0); d1 = LOAD_UINT32_LITTLE(d+1);
     440                 :            :         d2 = LOAD_UINT32_LITTLE(d+2); d3 = LOAD_UINT32_LITTLE(d+3);
     441                 :            :         d4 = LOAD_UINT32_LITTLE(d+4); d5 = LOAD_UINT32_LITTLE(d+5);
     442                 :            :         d6 = LOAD_UINT32_LITTLE(d+6); d7 = LOAD_UINT32_LITTLE(d+7);
     443                 :            :         k8 = *(k+8); k9 = *(k+9); k10 = *(k+10); k11 = *(k+11);
     444                 :            :         k12 = *(k+12); k13 = *(k+13); k14 = *(k+14); k15 = *(k+15);
     445                 :            :         
     446                 :            :         h1 += MUL64((k0 + d0), (k4 + d4));
     447                 :            :         h2 += MUL64((k4 + d0), (k8 + d4));
     448                 :            :         h3 += MUL64((k8 + d0), (k12 + d4));
     449                 :            :         
     450                 :            :         h1 += MUL64((k1 + d1), (k5 + d5));
     451                 :            :         h2 += MUL64((k5 + d1), (k9 + d5));
     452                 :            :         h3 += MUL64((k9 + d1), (k13 + d5));
     453                 :            :         
     454                 :            :         h1 += MUL64((k2 + d2), (k6 + d6));
     455                 :            :         h2 += MUL64((k6 + d2), (k10 + d6));
     456                 :            :         h3 += MUL64((k10 + d2), (k14 + d6));
     457                 :            :         
     458                 :            :         h1 += MUL64((k3 + d3), (k7 + d7));
     459                 :            :         h2 += MUL64((k7 + d3), (k11 + d7));
     460                 :            :         h3 += MUL64((k11 + d3), (k15 + d7));
     461                 :            :         
     462                 :            :         k0 = k8; k1 = k9; k2 = k10; k3 = k11;
     463                 :            :         k4 = k12; k5 = k13; k6 = k14; k7 = k15;
     464                 :            :         
     465                 :            :         d += 8;
     466                 :            :         k += 8;
     467                 :            :     } while (--c);
     468                 :            :     ((UINT64 *)hp)[0] = h1;
     469                 :            :     ((UINT64 *)hp)[1] = h2;
     470                 :            :     ((UINT64 *)hp)[2] = h3;
     471                 :            : }
     472                 :            : 
     473                 :            : #elif (UMAC_OUTPUT_LEN == 16)
     474                 :            : 
     475                 :       3567 : static void nh_aux(void *kp, const void *dp, void *hp, UINT32 dlen)
     476                 :            : /* Same as previous nh_aux, but two streams are handled in one pass,
     477                 :            :  * reading and writing 24 bytes of hash-state per call.
     478                 :            : */
     479                 :            : {
     480                 :            :     UINT64 h1,h2,h3,h4;
     481                 :       3567 :     UWORD c = dlen / 32;
     482                 :       3567 :     UINT32 *k = (UINT32 *)kp;
     483                 :       3567 :     const UINT32 *d = (const UINT32 *)dp;
     484                 :            :     UINT32 d0,d1,d2,d3,d4,d5,d6,d7;
     485                 :            :     UINT32 k0,k1,k2,k3,k4,k5,k6,k7,
     486                 :            :         k8,k9,k10,k11,k12,k13,k14,k15,
     487                 :            :         k16,k17,k18,k19;
     488                 :            :     
     489                 :       3567 :     h1 = *((UINT64 *)hp);
     490                 :       3567 :     h2 = *((UINT64 *)hp + 1);
     491                 :       3567 :     h3 = *((UINT64 *)hp + 2);
     492                 :       3567 :     h4 = *((UINT64 *)hp + 3);
     493                 :       3567 :     k0 = *(k+0); k1 = *(k+1); k2 = *(k+2); k3 = *(k+3);
     494                 :       3567 :     k4 = *(k+4); k5 = *(k+5); k6 = *(k+6); k7 = *(k+7);
     495                 :            :     do {
     496                 :      77759 :         d0 = LOAD_UINT32_LITTLE(d+0); d1 = LOAD_UINT32_LITTLE(d+1);
     497                 :      77759 :         d2 = LOAD_UINT32_LITTLE(d+2); d3 = LOAD_UINT32_LITTLE(d+3);
     498                 :      77759 :         d4 = LOAD_UINT32_LITTLE(d+4); d5 = LOAD_UINT32_LITTLE(d+5);
     499                 :      77759 :         d6 = LOAD_UINT32_LITTLE(d+6); d7 = LOAD_UINT32_LITTLE(d+7);
     500                 :      77759 :         k8 = *(k+8); k9 = *(k+9); k10 = *(k+10); k11 = *(k+11);
     501                 :      77759 :         k12 = *(k+12); k13 = *(k+13); k14 = *(k+14); k15 = *(k+15);
     502                 :      77759 :         k16 = *(k+16); k17 = *(k+17); k18 = *(k+18); k19 = *(k+19);
     503                 :            :         
     504                 :      77759 :         h1 += MUL64((k0 + d0), (k4 + d4));
     505                 :      77759 :         h2 += MUL64((k4 + d0), (k8 + d4));
     506                 :      77759 :         h3 += MUL64((k8 + d0), (k12 + d4));
     507                 :      77759 :         h4 += MUL64((k12 + d0), (k16 + d4));
     508                 :            :         
     509                 :      77759 :         h1 += MUL64((k1 + d1), (k5 + d5));
     510                 :      77759 :         h2 += MUL64((k5 + d1), (k9 + d5));
     511                 :      77759 :         h3 += MUL64((k9 + d1), (k13 + d5));
     512                 :      77759 :         h4 += MUL64((k13 + d1), (k17 + d5));
     513                 :            :         
     514                 :      77759 :         h1 += MUL64((k2 + d2), (k6 + d6));
     515                 :      77759 :         h2 += MUL64((k6 + d2), (k10 + d6));
     516                 :      77759 :         h3 += MUL64((k10 + d2), (k14 + d6));
     517                 :      77759 :         h4 += MUL64((k14 + d2), (k18 + d6));
     518                 :            :         
     519                 :      77759 :         h1 += MUL64((k3 + d3), (k7 + d7));
     520                 :      77759 :         h2 += MUL64((k7 + d3), (k11 + d7));
     521                 :      77759 :         h3 += MUL64((k11 + d3), (k15 + d7));
     522                 :      77759 :         h4 += MUL64((k15 + d3), (k19 + d7));
     523                 :            :         
     524                 :      77759 :         k0 = k8; k1 = k9; k2 = k10; k3 = k11;
     525                 :      77759 :         k4 = k12; k5 = k13; k6 = k14; k7 = k15;
     526                 :      77759 :         k8 = k16; k9 = k17; k10 = k18; k11 = k19;
     527                 :            :         
     528                 :      77759 :         d += 8;
     529                 :      77759 :         k += 8;
     530         [ +  + ]:      77759 :     } while (--c);
     531                 :       3567 :     ((UINT64 *)hp)[0] = h1;
     532                 :       3567 :     ((UINT64 *)hp)[1] = h2;
     533                 :       3567 :     ((UINT64 *)hp)[2] = h3;
     534                 :       3567 :     ((UINT64 *)hp)[3] = h4;
     535                 :       3567 : }
     536                 :            : 
     537                 :            : /* ---------------------------------------------------------------------- */
     538                 :            : #endif  /* UMAC_OUTPUT_LENGTH */
     539                 :            : /* ---------------------------------------------------------------------- */
     540                 :            : 
     541                 :            : 
     542                 :            : /* ---------------------------------------------------------------------- */
     543                 :            : 
     544                 :            : static void nh_transform(nh_ctx *hc, const UINT8 *buf, UINT32 nbytes)
     545                 :            : /* This function is a wrapper for the primitive NH hash functions. It takes
     546                 :            :  * as argument "hc" the current hash context and a buffer which must be a
     547                 :            :  * multiple of L1_PAD_BOUNDARY. The key passed to nh_aux is offset
     548                 :            :  * appropriately according to how much message has been hashed already.
     549                 :            :  */
     550                 :            : {
     551                 :            :     UINT8 *key;
     552                 :            :   
     553                 :       2599 :     key = hc->nh_key + hc->bytes_hashed;
     554                 :       2599 :     nh_aux(key, buf, hc->state, nbytes);
     555                 :            : }
     556                 :            : 
     557                 :            : /* ---------------------------------------------------------------------- */
     558                 :            : 
     559                 :            : #if (__LITTLE_ENDIAN__)
     560                 :       2278 : static void endian_convert(void *buf, UWORD bpw, UINT32 num_bytes)
     561                 :            : /* We endian convert the keys on little-endian computers to               */
     562                 :            : /* compensate for the lack of big-endian memory reads during hashing.     */
     563                 :            : {
     564                 :       2278 :     UWORD iters = num_bytes / bpw;
     565         [ +  + ]:       2278 :     if (bpw == 4) {
     566                 :            :         UINT32 *p = (UINT32 *)buf;
     567                 :            :         do {
     568                 :     101924 :             *p = LOAD_UINT32_REVERSED(p);
     569                 :     101924 :             p++;
     570         [ +  + ]:     101924 :         } while (--iters);
     571         [ +  - ]:       1514 :     } else if (bpw == 8) {
     572                 :            :         UINT32 *p = (UINT32 *)buf;
     573                 :            :         UINT32 t;
     574                 :            :         do {
     575                 :      11320 :             t = LOAD_UINT32_REVERSED(p+1);
     576                 :      11320 :             p[1] = LOAD_UINT32_REVERSED(p);
     577                 :       5660 :             p[0] = t;
     578                 :       5660 :             p += 2;
     579         [ +  + ]:       5660 :         } while (--iters);
     580                 :            :     }
     581                 :       2278 : }
     582                 :            : #define endian_convert_if_le(x,y,z) endian_convert((x),(y),(z))
     583                 :            : #else
     584                 :            : #define endian_convert_if_le(x,y,z) do{}while(0)  /* Do nothing */
     585                 :            : #endif
     586                 :            : 
     587                 :            : /* ---------------------------------------------------------------------- */
     588                 :            : 
     589                 :            : static void nh_reset(nh_ctx *hc)
     590                 :            : /* Reset nh_ctx to ready for hashing of new data */
     591                 :            : {
     592                 :       4686 :     hc->bytes_hashed = 0;
     593                 :       4686 :     hc->next_data_empty = 0;
     594                 :       4686 :     hc->state[0] = 0;
     595                 :            : #if (UMAC_OUTPUT_LEN >= 8)
     596                 :       4686 :     hc->state[1] = 0;
     597                 :            : #endif
     598                 :            : #if (UMAC_OUTPUT_LEN >= 12)
     599                 :       2280 :     hc->state[2] = 0;
     600                 :            : #endif
     601                 :            : #if (UMAC_OUTPUT_LEN == 16)
     602                 :       2280 :     hc->state[3] = 0;
     603                 :            : #endif
     604                 :            : 
     605                 :            : }
     606                 :            : 
     607                 :            : /* ---------------------------------------------------------------------- */
     608                 :            : 
     609                 :        382 : static void nh_init(nh_ctx *hc, aes_int_key prf_key)
     610                 :            : /* Generate nh_key, endian convert and reset to be ready for hashing.   */
     611                 :            : {
     612                 :        382 :     kdf(hc->nh_key, prf_key, 1, sizeof(hc->nh_key));
     613                 :        382 :     endian_convert_if_le(hc->nh_key, 4, sizeof(hc->nh_key));
     614                 :            :     nh_reset(hc);
     615                 :        382 : }
     616                 :            : 
     617                 :            : /* ---------------------------------------------------------------------- */
     618                 :            : 
     619                 :       2152 : static void nh_update(nh_ctx *hc, const UINT8 *buf, UINT32 nbytes)
     620                 :            : /* Incorporate nbytes of data into a nh_ctx, buffer whatever is not an    */
     621                 :            : /* even multiple of HASH_BUF_BYTES.                                       */
     622                 :            : {
     623                 :            :     UINT32 i,j;
     624                 :            :     
     625                 :       2152 :     j = hc->next_data_empty;
     626         [ +  + ]:       2152 :     if ((j + nbytes) >= HASH_BUF_BYTES) {
     627         [ -  + ]:        488 :         if (j) {
     628                 :          0 :             i = HASH_BUF_BYTES - j;
     629                 :          0 :             memcpy(hc->data+j, buf, i);
     630                 :          0 :             nh_transform(hc,hc->data,HASH_BUF_BYTES);
     631                 :          0 :             nbytes -= i;
     632                 :          0 :             buf += i;
     633                 :          0 :             hc->bytes_hashed += HASH_BUF_BYTES;
     634                 :            :         }
     635         [ +  - ]:        488 :         if (nbytes >= HASH_BUF_BYTES) {
     636                 :        488 :             i = nbytes & ~(HASH_BUF_BYTES - 1);
     637                 :            :             nh_transform(hc, buf, i);
     638                 :        488 :             nbytes -= i;
     639                 :        488 :             buf += i;
     640                 :        488 :             hc->bytes_hashed += i;
     641                 :            :         }
     642                 :            :         j = 0;
     643                 :            :     }
     644                 :       2152 :     memcpy(hc->data + j, buf, nbytes);
     645                 :       2152 :     hc->next_data_empty = j + nbytes;
     646                 :       2152 : }
     647                 :            : 
     648                 :            : /* ---------------------------------------------------------------------- */
     649                 :            : 
     650                 :       2111 : static void zero_pad(UINT8 *p, int nbytes)
     651                 :            : {
     652                 :            : /* Write "nbytes" of zeroes, beginning at "p" */
     653         [ +  + ]:       2111 :     if (nbytes >= (int)sizeof(UWORD)) {
     654         [ -  + ]:       1712 :         while ((ptrdiff_t)p % sizeof(UWORD)) {
     655                 :          0 :             *p = 0;
     656                 :          0 :             nbytes--;
     657                 :          0 :             p++;
     658                 :            :         }
     659         [ +  + ]:       9255 :         while (nbytes >= (int)sizeof(UWORD)) {
     660                 :       7144 :             *(UWORD *)p = 0;
     661                 :       7144 :             nbytes -= sizeof(UWORD);
     662                 :       7144 :             p += sizeof(UWORD);
     663                 :            :         }
     664                 :            :     }
     665         [ -  + ]:       2111 :     while (nbytes) {
     666                 :          0 :         *p = 0;
     667                 :          0 :         nbytes--;
     668                 :          0 :         p++;
     669                 :            :     }
     670                 :       2111 : }
     671                 :            : 
     672                 :            : /* ---------------------------------------------------------------------- */
     673                 :            : 
     674                 :       2152 : static void nh_final(nh_ctx *hc, UINT8 *result)
     675                 :            : /* After passing some number of data buffers to nh_update() for integration
     676                 :            :  * into an NH context, nh_final is called to produce a hash result. If any
     677                 :            :  * bytes are in the buffer hc->data, incorporate them into the
     678                 :            :  * NH context. Finally, add into the NH accumulation "state" the total number
     679                 :            :  * of bits hashed. The resulting numbers are written to the buffer "result".
     680                 :            :  * If nh_update was never called, L1_PAD_BOUNDARY zeroes are incorporated.
     681                 :            :  */
     682                 :            : {
     683                 :            :     int nh_len, nbits;
     684                 :            : 
     685         [ +  + ]:       2152 :     if (hc->next_data_empty != 0) {
     686                 :       2111 :         nh_len = ((hc->next_data_empty + (L1_PAD_BOUNDARY - 1)) &
     687                 :            :                                                 ~(L1_PAD_BOUNDARY - 1));
     688                 :       2111 :         zero_pad(hc->data + hc->next_data_empty, 
     689                 :            :                                           nh_len - hc->next_data_empty);
     690                 :       2111 :         nh_transform(hc, hc->data, nh_len);
     691                 :       2111 :         hc->bytes_hashed += hc->next_data_empty;
     692         [ -  + ]:         41 :     } else if (hc->bytes_hashed == 0) {
     693                 :          0 :         nh_len = L1_PAD_BOUNDARY;
     694                 :          0 :         zero_pad(hc->data, L1_PAD_BOUNDARY);
     695                 :          0 :         nh_transform(hc, hc->data, nh_len);
     696                 :            :     }
     697                 :            : 
     698                 :       2152 :     nbits = (hc->bytes_hashed << 3);
     699                 :       2152 :     ((UINT64 *)result)[0] = ((UINT64 *)hc->state)[0] + nbits;
     700                 :            : #if (UMAC_OUTPUT_LEN >= 8)
     701                 :       2152 :     ((UINT64 *)result)[1] = ((UINT64 *)hc->state)[1] + nbits;
     702                 :            : #endif
     703                 :            : #if (UMAC_OUTPUT_LEN >= 12)
     704                 :       1048 :     ((UINT64 *)result)[2] = ((UINT64 *)hc->state)[2] + nbits;
     705                 :            : #endif
     706                 :            : #if (UMAC_OUTPUT_LEN == 16)
     707                 :       1048 :     ((UINT64 *)result)[3] = ((UINT64 *)hc->state)[3] + nbits;
     708                 :            : #endif
     709                 :            :     nh_reset(hc);
     710                 :       2152 : }
     711                 :            : 
     712                 :            : /* ---------------------------------------------------------------------- */
     713                 :            : 
     714                 :            : static void nh(nh_ctx *hc, const UINT8 *buf, UINT32 padded_len,
     715                 :            :                UINT32 unpadded_len, UINT8 *result)
     716                 :            : /* All-in-one nh_update() and nh_final() equivalent.
     717                 :            :  * Assumes that padded_len is divisible by L1_PAD_BOUNDARY and result is
     718                 :            :  * well aligned
     719                 :            :  */
     720                 :            : {
     721                 :            :     UINT32 nbits;
     722                 :            :     
     723                 :            :     /* Initialize the hash state */
     724                 :       4612 :     nbits = (unpadded_len << 3);
     725                 :            :     
     726                 :       4612 :     ((UINT64 *)result)[0] = nbits;
     727                 :            : #if (UMAC_OUTPUT_LEN >= 8)
     728                 :       4612 :     ((UINT64 *)result)[1] = nbits;
     729                 :            : #endif
     730                 :            : #if (UMAC_OUTPUT_LEN >= 12)
     731                 :       2306 :     ((UINT64 *)result)[2] = nbits;
     732                 :            : #endif
     733                 :            : #if (UMAC_OUTPUT_LEN == 16)
     734                 :       2306 :     ((UINT64 *)result)[3] = nbits;
     735                 :            : #endif
     736                 :            :     
     737                 :       4612 :     nh_aux(hc->nh_key, buf, result, padded_len);
     738                 :            : }
     739                 :            : 
     740                 :            : /* ---------------------------------------------------------------------- */
     741                 :            : /* ---------------------------------------------------------------------- */
     742                 :            : /* ----- Begin UHASH Section -------------------------------------------- */
     743                 :            : /* ---------------------------------------------------------------------- */
     744                 :            : /* ---------------------------------------------------------------------- */
     745                 :            : 
     746                 :            : /* UHASH is a multi-layered algorithm. Data presented to UHASH is first
     747                 :            :  * hashed by NH. The NH output is then hashed by a polynomial-hash layer
     748                 :            :  * unless the initial data to be hashed is short. After the polynomial-
     749                 :            :  * layer, an inner-product hash is used to produce the final UHASH output.
     750                 :            :  *
     751                 :            :  * UHASH provides two interfaces, one all-at-once and another where data
     752                 :            :  * buffers are presented sequentially. In the sequential interface, the
     753                 :            :  * UHASH client calls the routine uhash_update() as many times as necessary.
     754                 :            :  * When there is no more data to be fed to UHASH, the client calls
     755                 :            :  * uhash_final() which          
     756                 :            :  * calculates the UHASH output. Before beginning another UHASH calculation    
     757                 :            :  * the uhash_reset() routine must be called. The all-at-once UHASH routine,   
     758                 :            :  * uhash(), is equivalent to the sequence of calls uhash_update() and         
     759                 :            :  * uhash_final(); however it is optimized and should be                     
     760                 :            :  * used whenever the sequential interface is not necessary.              
     761                 :            :  *                                                                        
     762                 :            :  * The routine uhash_init() initializes the uhash_ctx data structure and    
     763                 :            :  * must be called once, before any other UHASH routine.
     764                 :            :  */                                                        
     765                 :            : 
     766                 :            : /* ---------------------------------------------------------------------- */
     767                 :            : /* ----- Constants and uhash_ctx ---------------------------------------- */
     768                 :            : /* ---------------------------------------------------------------------- */
     769                 :            : 
     770                 :            : /* ---------------------------------------------------------------------- */
     771                 :            : /* ----- Poly hash and Inner-Product hash Constants --------------------- */
     772                 :            : /* ---------------------------------------------------------------------- */
     773                 :            : 
     774                 :            : /* Primes and masks */
     775                 :            : #define p36    ((UINT64)0x0000000FFFFFFFFBull)              /* 2^36 -  5 */
     776                 :            : #define p64    ((UINT64)0xFFFFFFFFFFFFFFC5ull)              /* 2^64 - 59 */
     777                 :            : #define m36    ((UINT64)0x0000000FFFFFFFFFull)  /* The low 36 of 64 bits */
     778                 :            : 
     779                 :            : 
     780                 :            : /* ---------------------------------------------------------------------- */
     781                 :            : 
     782                 :            : typedef struct uhash_ctx {
     783                 :            :     nh_ctx hash;                          /* Hash context for L1 NH hash  */
     784                 :            :     UINT64 poly_key_8[STREAMS];           /* p64 poly keys                */
     785                 :            :     UINT64 poly_accum[STREAMS];           /* poly hash result             */
     786                 :            :     UINT64 ip_keys[STREAMS*4];            /* Inner-product keys           */
     787                 :            :     UINT32 ip_trans[STREAMS];             /* Inner-product translation    */
     788                 :            :     UINT32 msg_len;                       /* Total length of data passed  */
     789                 :            :                                           /* to uhash */
     790                 :            : } uhash_ctx;
     791                 :            : typedef struct uhash_ctx *uhash_ctx_t;
     792                 :            : 
     793                 :            : /* ---------------------------------------------------------------------- */
     794                 :            : 
     795                 :            : 
     796                 :            : /* The polynomial hashes use Horner's rule to evaluate a polynomial one
     797                 :            :  * word at a time. As described in the specification, poly32 and poly64
     798                 :            :  * require keys from special domains. The following implementations exploit
     799                 :            :  * the special domains to avoid overflow. The results are not guaranteed to
     800                 :            :  * be within Z_p32 and Z_p64, but the Inner-Product hash implementation
     801                 :            :  * patches any errant values.
     802                 :            :  */
     803                 :            : 
     804                 :      14436 : static UINT64 poly64(UINT64 cur, UINT64 key, UINT64 data)
     805                 :            : {
     806                 :      14436 :     UINT32 key_hi = (UINT32)(key >> 32),
     807                 :      14436 :            key_lo = (UINT32)key,
     808                 :      14436 :            cur_hi = (UINT32)(cur >> 32),
     809                 :      14436 :            cur_lo = (UINT32)cur,
     810                 :            :            x_lo,
     811                 :            :            x_hi;
     812                 :            :     UINT64 X,T,res;
     813                 :            :     
     814                 :      14436 :     X =  MUL64(key_hi, cur_lo) + MUL64(cur_hi, key_lo);
     815                 :      14436 :     x_lo = (UINT32)X;
     816                 :      14436 :     x_hi = (UINT32)(X >> 32);
     817                 :            :     
     818                 :      14436 :     res = (MUL64(key_hi, cur_hi) + x_hi) * 59 + MUL64(key_lo, cur_lo);
     819                 :            :      
     820                 :      14436 :     T = ((UINT64)x_lo << 32);
     821                 :      14436 :     res += T;
     822         [ +  + ]:      14436 :     if (res < T)
     823                 :       1628 :         res += 59;
     824                 :            : 
     825                 :      14436 :     res += data;
     826         [ +  + ]:      14436 :     if (res < data)
     827                 :       6973 :         res += 59;
     828                 :            : 
     829                 :      14436 :     return res;
     830                 :            : }
     831                 :            : 
     832                 :            : 
     833                 :            : /* Although UMAC is specified to use a ramped polynomial hash scheme, this
     834                 :            :  * implementation does not handle all ramp levels. Because we don't handle
     835                 :            :  * the ramp up to p128 modulus in this implementation, we are limited to
     836                 :            :  * 2^14 poly_hash() invocations per stream (for a total capacity of 2^24
     837                 :            :  * bytes input to UMAC per tag, ie. 16MB).
     838                 :            :  */
     839                 :       4812 : static void poly_hash(uhash_ctx_t hc, UINT32 data_in[])
     840                 :            : {
     841                 :            :     int i;
     842                 :       4812 :     UINT64 *data=(UINT64*)data_in;
     843                 :            :     
     844         [ +  + ]:      19248 :     for (i = 0; i < STREAMS; i++) {
     845         [ -  + ]:      14436 :         if ((UINT32)(data[i] >> 32) == 0xfffffffful) {
     846                 :          0 :             hc->poly_accum[i] = poly64(hc->poly_accum[i], 
     847                 :            :                                        hc->poly_key_8[i], p64 - 1);
     848                 :          0 :             hc->poly_accum[i] = poly64(hc->poly_accum[i],
     849                 :          0 :                                        hc->poly_key_8[i], (data[i] - 59));
     850                 :            :         } else {
     851                 :      14436 :             hc->poly_accum[i] = poly64(hc->poly_accum[i],
     852                 :            :                                        hc->poly_key_8[i], data[i]);
     853                 :            :         }
     854                 :            :     }
     855                 :       4812 : }
     856                 :            : 
     857                 :            : 
     858                 :            : /* ---------------------------------------------------------------------- */
     859                 :            : 
     860                 :            : 
     861                 :            : /* The final step in UHASH is an inner-product hash. The poly hash
     862                 :            :  * produces a result not neccesarily WORD_LEN bytes long. The inner-
     863                 :            :  * product hash breaks the polyhash output into 16-bit chunks and
     864                 :            :  * multiplies each with a 36 bit key.
     865                 :            :  */
     866                 :            : 
     867                 :            : static UINT64 ip_aux(UINT64 t, UINT64 *ipkp, UINT64 data)
     868                 :            : {
     869                 :       6400 :     t = t + ipkp[0] * (UINT64)(UINT16)(data >> 48);
     870                 :       6400 :     t = t + ipkp[1] * (UINT64)(UINT16)(data >> 32);
     871                 :       6400 :     t = t + ipkp[2] * (UINT64)(UINT16)(data >> 16);
     872                 :       6400 :     t = t + ipkp[3] * (UINT64)(UINT16)(data);
     873                 :            :     
     874                 :            :     return t;
     875                 :            : }
     876                 :            : 
     877                 :            : static UINT32 ip_reduce_p36(UINT64 t)
     878                 :            : {
     879                 :            : /* Divisionless modular reduction */
     880                 :            :     UINT64 ret;
     881                 :            :     
     882                 :       6400 :     ret = (t & m36) + 5 * (t >> 36);
     883 [ -  + ][ -  + ]:       2552 :     if (ret >= p36)
         [ -  + ][ -  + ]
                 [ -  + ]
     884                 :          0 :         ret -= p36;
     885                 :            : 
     886                 :            :     /* return least significant 32 bits */
     887                 :       6400 :     return (UINT32)(ret);
     888                 :            : }
     889                 :            : 
     890                 :            : 
     891                 :            : /* If the data being hashed by UHASH is no longer than L1_KEY_LEN, then
     892                 :            :  * the polyhash stage is skipped and ip_short is applied directly to the
     893                 :            :  * NH output.
     894                 :            :  */
     895                 :       1952 : static void ip_short(uhash_ctx_t ahc, UINT8 *nh_res, u_char *res)
     896                 :            : {
     897                 :            :     UINT64 t;
     898                 :       1952 :     UINT64 *nhp = (UINT64 *)nh_res;
     899                 :            :     
     900                 :       3904 :     t  = ip_aux(0,ahc->ip_keys, nhp[0]);
     901                 :       1952 :     STORE_UINT32_BIG((UINT32 *)res+0, ip_reduce_p36(t) ^ ahc->ip_trans[0]);
     902                 :            : #if (UMAC_OUTPUT_LEN >= 8)
     903                 :       3904 :     t  = ip_aux(0,ahc->ip_keys+4, nhp[1]);
     904                 :       1952 :     STORE_UINT32_BIG((UINT32 *)res+1, ip_reduce_p36(t) ^ ahc->ip_trans[1]);
     905                 :            : #endif
     906                 :            : #if (UMAC_OUTPUT_LEN >= 12)
     907                 :       1896 :     t  = ip_aux(0,ahc->ip_keys+8, nhp[2]);
     908                 :        948 :     STORE_UINT32_BIG((UINT32 *)res+2, ip_reduce_p36(t) ^ ahc->ip_trans[2]);
     909                 :            : #endif
     910                 :            : #if (UMAC_OUTPUT_LEN == 16)
     911                 :       1896 :     t  = ip_aux(0,ahc->ip_keys+12, nhp[3]);
     912                 :        948 :     STORE_UINT32_BIG((UINT32 *)res+3, ip_reduce_p36(t) ^ ahc->ip_trans[3]);
     913                 :            : #endif
     914                 :       1952 : }
     915                 :            : 
     916                 :            : /* If the data being hashed by UHASH is longer than L1_KEY_LEN, then
     917                 :            :  * the polyhash stage is not skipped and ip_long is applied to the
     918                 :            :  * polyhash output.
     919                 :            :  */
     920                 :        200 : static void ip_long(uhash_ctx_t ahc, u_char *res)
     921                 :            : {
     922                 :            :     int i;
     923                 :            :     UINT64 t;
     924                 :            : 
     925         [ +  + ]:        800 :     for (i = 0; i < STREAMS; i++) {
     926                 :            :         /* fix polyhash output not in Z_p64 */
     927         [ -  + ]:        600 :         if (ahc->poly_accum[i] >= p64)
     928                 :          0 :             ahc->poly_accum[i] -= p64;
     929                 :       1200 :         t  = ip_aux(0,ahc->ip_keys+(i*4), ahc->poly_accum[i]);
     930                 :        600 :         STORE_UINT32_BIG((UINT32 *)res+i, 
     931                 :            :                          ip_reduce_p36(t) ^ ahc->ip_trans[i]);
     932                 :            :     }
     933                 :        200 : }
     934                 :            : 
     935                 :            : 
     936                 :            : /* ---------------------------------------------------------------------- */
     937                 :            : 
     938                 :            : /* ---------------------------------------------------------------------- */
     939                 :            : 
     940                 :            : /* Reset uhash context for next hash session */
     941                 :            : static int uhash_reset(uhash_ctx_t pc)
     942                 :            : {
     943                 :       2152 :     nh_reset(&pc->hash);
     944                 :       2152 :     pc->msg_len = 0;
     945                 :       2152 :     pc->poly_accum[0] = 1;
     946                 :            : #if (UMAC_OUTPUT_LEN >= 8)
     947                 :       2152 :     pc->poly_accum[1] = 1;
     948                 :            : #endif
     949                 :            : #if (UMAC_OUTPUT_LEN >= 12)
     950                 :       1048 :     pc->poly_accum[2] = 1;
     951                 :            : #endif
     952                 :            : #if (UMAC_OUTPUT_LEN == 16)
     953                 :       1048 :     pc->poly_accum[3] = 1;
     954                 :            : #endif
     955                 :            :     return 1;
     956                 :            : }
     957                 :            : 
     958                 :            : /* ---------------------------------------------------------------------- */
     959                 :            : 
     960                 :            : /* Given a pointer to the internal key needed by kdf() and a uhash context,
     961                 :            :  * initialize the NH context and generate keys needed for poly and inner-
     962                 :            :  * product hashing. All keys are endian adjusted in memory so that native
     963                 :            :  * loads cause correct keys to be in registers during calculation.
     964                 :            :  */
     965                 :        382 : static void uhash_init(uhash_ctx_t ahc, aes_int_key prf_key)
     966                 :            : {
     967                 :            :     int i;
     968                 :            :     UINT8 buf[(8*STREAMS+4)*sizeof(UINT64)];
     969                 :            :     
     970                 :            :     /* Zero the entire uhash context */
     971                 :            :     memset(ahc, 0, sizeof(uhash_ctx));
     972                 :            : 
     973                 :            :     /* Initialize the L1 hash */
     974                 :        382 :     nh_init(&ahc->hash, prf_key);
     975                 :            :     
     976                 :            :     /* Setup L2 hash variables */
     977                 :        382 :     kdf(buf, prf_key, 2, sizeof(buf));    /* Fill buffer with index 1 key */
     978         [ +  + ]:       1514 :     for (i = 0; i < STREAMS; i++) {
     979                 :            :         /* Fill keys from the buffer, skipping bytes in the buffer not
     980                 :            :          * used by this implementation. Endian reverse the keys if on a
     981                 :            :          * little-endian computer.
     982                 :            :          */
     983                 :       1132 :         memcpy(ahc->poly_key_8+i, buf+24*i, 8);
     984                 :       1132 :         endian_convert_if_le(ahc->poly_key_8+i, 8, 8);
     985                 :            :         /* Mask the 64-bit keys to their special domain */
     986                 :       1132 :         ahc->poly_key_8[i] &= ((UINT64)0x01ffffffu << 32) + 0x01ffffffu;
     987                 :       1132 :         ahc->poly_accum[i] = 1;  /* Our polyhash prepends a non-zero word */
     988                 :            :     }
     989                 :            :     
     990                 :            :     /* Setup L3-1 hash variables */
     991                 :        382 :     kdf(buf, prf_key, 3, sizeof(buf)); /* Fill buffer with index 2 key */
     992         [ +  + ]:       1514 :     for (i = 0; i < STREAMS; i++)
     993                 :       1132 :           memcpy(ahc->ip_keys+4*i, buf+(8*i+4)*sizeof(UINT64),
     994                 :            :                                                  4*sizeof(UINT64));
     995                 :        382 :     endian_convert_if_le(ahc->ip_keys, sizeof(UINT64), 
     996                 :            :                                                   sizeof(ahc->ip_keys));
     997         [ +  + ]:       4910 :     for (i = 0; i < STREAMS*4; i++)
     998                 :       4528 :         ahc->ip_keys[i] %= p36;  /* Bring into Z_p36 */
     999                 :            :     
    1000                 :            :     /* Setup L3-2 hash variables    */
    1001                 :            :     /* Fill buffer with index 4 key */
    1002                 :        382 :     kdf(ahc->ip_trans, prf_key, 4, STREAMS * sizeof(UINT32));
    1003                 :        382 :     endian_convert_if_le(ahc->ip_trans, sizeof(UINT32),
    1004                 :            :                          STREAMS * sizeof(UINT32));
    1005                 :        382 : }
    1006                 :            : 
    1007                 :            : /* ---------------------------------------------------------------------- */
    1008                 :            : 
    1009                 :            : #if 0
    1010                 :            : static uhash_ctx_t uhash_alloc(u_char key[])
    1011                 :            : {
    1012                 :            : /* Allocate memory and force to a 16-byte boundary. */
    1013                 :            :     uhash_ctx_t ctx;
    1014                 :            :     u_char bytes_to_add;
    1015                 :            :     aes_int_key prf_key;
    1016                 :            :     
    1017                 :            :     ctx = (uhash_ctx_t)malloc(sizeof(uhash_ctx)+ALLOC_BOUNDARY);
    1018                 :            :     if (ctx) {
    1019                 :            :         if (ALLOC_BOUNDARY) {
    1020                 :            :             bytes_to_add = ALLOC_BOUNDARY -
    1021                 :            :                               ((ptrdiff_t)ctx & (ALLOC_BOUNDARY -1));
    1022                 :            :             ctx = (uhash_ctx_t)((u_char *)ctx + bytes_to_add);
    1023                 :            :             *((u_char *)ctx - 1) = bytes_to_add;
    1024                 :            :         }
    1025                 :            :         aes_key_setup(key,prf_key);
    1026                 :            :         uhash_init(ctx, prf_key);
    1027                 :            :     }
    1028                 :            :     return (ctx);
    1029                 :            : }
    1030                 :            : #endif
    1031                 :            : 
    1032                 :            : /* ---------------------------------------------------------------------- */
    1033                 :            : 
    1034                 :            : #if 0
    1035                 :            : static int uhash_free(uhash_ctx_t ctx)
    1036                 :            : {
    1037                 :            : /* Free memory allocated by uhash_alloc */
    1038                 :            :     u_char bytes_to_sub;
    1039                 :            :     
    1040                 :            :     if (ctx) {
    1041                 :            :         if (ALLOC_BOUNDARY) {
    1042                 :            :             bytes_to_sub = *((u_char *)ctx - 1);
    1043                 :            :             ctx = (uhash_ctx_t)((u_char *)ctx - bytes_to_sub);
    1044                 :            :         }
    1045                 :            :         free(ctx);
    1046                 :            :     }
    1047                 :            :     return (1);
    1048                 :            : }
    1049                 :            : #endif
    1050                 :            : /* ---------------------------------------------------------------------- */
    1051                 :            : 
    1052                 :       2152 : static int uhash_update(uhash_ctx_t ctx, const u_char *input, long len)
    1053                 :            : /* Given len bytes of data, we parse it into L1_KEY_LEN chunks and
    1054                 :            :  * hash each one with NH, calling the polyhash on each NH output.
    1055                 :            :  */
    1056                 :            : {
    1057                 :            :     UWORD bytes_hashed, bytes_remaining;
    1058                 :            :     UINT64 result_buf[STREAMS];
    1059                 :       2152 :     UINT8 *nh_result = (UINT8 *)&result_buf;
    1060                 :            :     
    1061         [ +  + ]:       2152 :     if (ctx->msg_len + len <= L1_KEY_LEN) {
    1062                 :       1952 :         nh_update(&ctx->hash, (const UINT8 *)input, len);
    1063                 :       1952 :         ctx->msg_len += len;
    1064                 :            :     } else {
    1065                 :            :     
    1066                 :        200 :          bytes_hashed = ctx->msg_len % L1_KEY_LEN;
    1067         [ -  + ]:        200 :          if (ctx->msg_len == L1_KEY_LEN)
    1068                 :          0 :              bytes_hashed = L1_KEY_LEN;
    1069                 :            : 
    1070         [ +  - ]:        200 :          if (bytes_hashed + len >= L1_KEY_LEN) {
    1071                 :            : 
    1072                 :            :              /* If some bytes have been passed to the hash function      */
    1073                 :            :              /* then we want to pass at most (L1_KEY_LEN - bytes_hashed) */
    1074                 :            :              /* bytes to complete the current nh_block.                  */
    1075         [ -  + ]:        200 :              if (bytes_hashed) {
    1076                 :          0 :                  bytes_remaining = (L1_KEY_LEN - bytes_hashed);
    1077                 :          0 :                  nh_update(&ctx->hash, (const UINT8 *)input, bytes_remaining);
    1078                 :          0 :                  nh_final(&ctx->hash, nh_result);
    1079                 :          0 :                  ctx->msg_len += bytes_remaining;
    1080                 :          0 :                  poly_hash(ctx,(UINT32 *)nh_result);
    1081                 :          0 :                  len -= bytes_remaining;
    1082                 :        200 :                  input += bytes_remaining;
    1083                 :            :              }
    1084                 :            : 
    1085                 :            :              /* Hash directly from input stream if enough bytes */
    1086         [ +  + ]:       4812 :              while (len >= L1_KEY_LEN) {
    1087                 :       4612 :                  nh(&ctx->hash, (const UINT8 *)input, L1_KEY_LEN,
    1088                 :            :                                    L1_KEY_LEN, nh_result);
    1089                 :       4612 :                  ctx->msg_len += L1_KEY_LEN;
    1090                 :       4612 :                  len -= L1_KEY_LEN;
    1091                 :       4612 :                  input += L1_KEY_LEN;
    1092                 :       4612 :                  poly_hash(ctx,(UINT32 *)nh_result);
    1093                 :            :              }
    1094                 :            :          }
    1095                 :            : 
    1096                 :            :          /* pass remaining < L1_KEY_LEN bytes of input data to NH */
    1097         [ +  - ]:        200 :          if (len) {
    1098                 :        200 :              nh_update(&ctx->hash, (const UINT8 *)input, len);
    1099                 :        200 :              ctx->msg_len += len;
    1100                 :            :          }
    1101                 :            :      }
    1102                 :            : 
    1103                 :       2152 :     return (1);
    1104                 :            : }
    1105                 :            : 
    1106                 :            : /* ---------------------------------------------------------------------- */
    1107                 :            : 
    1108                 :       2152 : static int uhash_final(uhash_ctx_t ctx, u_char *res)
    1109                 :            : /* Incorporate any pending data, pad, and generate tag */
    1110                 :            : {
    1111                 :            :     UINT64 result_buf[STREAMS];
    1112                 :       2152 :     UINT8 *nh_result = (UINT8 *)&result_buf;
    1113                 :            : 
    1114         [ +  + ]:       2152 :     if (ctx->msg_len > L1_KEY_LEN) {
    1115         [ +  - ]:        200 :         if (ctx->msg_len % L1_KEY_LEN) {
    1116                 :        200 :             nh_final(&ctx->hash, nh_result);
    1117                 :        200 :             poly_hash(ctx,(UINT32 *)nh_result);
    1118                 :            :         }
    1119                 :        200 :         ip_long(ctx, res);
    1120                 :            :     } else {
    1121                 :       1952 :         nh_final(&ctx->hash, nh_result);
    1122                 :       1952 :         ip_short(ctx,nh_result, res);
    1123                 :            :     }
    1124                 :            :     uhash_reset(ctx);
    1125                 :       2152 :     return (1);
    1126                 :            : }
    1127                 :            : 
    1128                 :            : /* ---------------------------------------------------------------------- */
    1129                 :            : 
    1130                 :            : #if 0
    1131                 :            : static int uhash(uhash_ctx_t ahc, u_char *msg, long len, u_char *res)
    1132                 :            : /* assumes that msg is in a writable buffer of length divisible by */
    1133                 :            : /* L1_PAD_BOUNDARY. Bytes beyond msg[len] may be zeroed.           */
    1134                 :            : {
    1135                 :            :     UINT8 nh_result[STREAMS*sizeof(UINT64)];
    1136                 :            :     UINT32 nh_len;
    1137                 :            :     int extra_zeroes_needed;
    1138                 :            :         
    1139                 :            :     /* If the message to be hashed is no longer than L1_HASH_LEN, we skip
    1140                 :            :      * the polyhash.
    1141                 :            :      */
    1142                 :            :     if (len <= L1_KEY_LEN) {
    1143                 :            :         if (len == 0)                  /* If zero length messages will not */
    1144                 :            :                 nh_len = L1_PAD_BOUNDARY;  /* be seen, comment out this case   */ 
    1145                 :            :         else
    1146                 :            :                 nh_len = ((len + (L1_PAD_BOUNDARY - 1)) & ~(L1_PAD_BOUNDARY - 1));
    1147                 :            :         extra_zeroes_needed = nh_len - len;
    1148                 :            :         zero_pad((UINT8 *)msg + len, extra_zeroes_needed);
    1149                 :            :         nh(&ahc->hash, (UINT8 *)msg, nh_len, len, nh_result);
    1150                 :            :         ip_short(ahc,nh_result, res);
    1151                 :            :     } else {
    1152                 :            :         /* Otherwise, we hash each L1_KEY_LEN chunk with NH, passing the NH
    1153                 :            :          * output to poly_hash().
    1154                 :            :          */
    1155                 :            :         do {
    1156                 :            :             nh(&ahc->hash, (UINT8 *)msg, L1_KEY_LEN, L1_KEY_LEN, nh_result);
    1157                 :            :             poly_hash(ahc,(UINT32 *)nh_result);
    1158                 :            :             len -= L1_KEY_LEN;
    1159                 :            :             msg += L1_KEY_LEN;
    1160                 :            :         } while (len >= L1_KEY_LEN);
    1161                 :            :         if (len) {
    1162                 :            :             nh_len = ((len + (L1_PAD_BOUNDARY - 1)) & ~(L1_PAD_BOUNDARY - 1));
    1163                 :            :             extra_zeroes_needed = nh_len - len;
    1164                 :            :             zero_pad((UINT8 *)msg + len, extra_zeroes_needed);
    1165                 :            :             nh(&ahc->hash, (UINT8 *)msg, nh_len, len, nh_result);
    1166                 :            :             poly_hash(ahc,(UINT32 *)nh_result);
    1167                 :            :         }
    1168                 :            : 
    1169                 :            :         ip_long(ahc, res);
    1170                 :            :     }
    1171                 :            :     
    1172                 :            :     uhash_reset(ahc);
    1173                 :            :     return 1;
    1174                 :            : }
    1175                 :            : #endif
    1176                 :            : 
    1177                 :            : /* ---------------------------------------------------------------------- */
    1178                 :            : /* ---------------------------------------------------------------------- */
    1179                 :            : /* ----- Begin UMAC Section --------------------------------------------- */
    1180                 :            : /* ---------------------------------------------------------------------- */
    1181                 :            : /* ---------------------------------------------------------------------- */
    1182                 :            : 
    1183                 :            : /* The UMAC interface has two interfaces, an all-at-once interface where
    1184                 :            :  * the entire message to be authenticated is passed to UMAC in one buffer,
    1185                 :            :  * and a sequential interface where the message is presented a little at a   
    1186                 :            :  * time. The all-at-once is more optimaized than the sequential version and
    1187                 :            :  * should be preferred when the sequential interface is not required. 
    1188                 :            :  */
    1189                 :            : struct umac_ctx {
    1190                 :            :     uhash_ctx hash;          /* Hash function for message compression    */
    1191                 :            :     pdf_ctx pdf;             /* PDF for hashed output                    */
    1192                 :            :     void *free_ptr;          /* Address to free this struct via          */
    1193                 :            : } umac_ctx;
    1194                 :            : 
    1195                 :            : /* ---------------------------------------------------------------------- */
    1196                 :            : 
    1197                 :            : #if 0
    1198                 :            : int umac_reset(struct umac_ctx *ctx)
    1199                 :            : /* Reset the hash function to begin a new authentication.        */
    1200                 :            : {
    1201                 :            :     uhash_reset(&ctx->hash);
    1202                 :            :     return (1);
    1203                 :            : }
    1204                 :            : #endif
    1205                 :            : 
    1206                 :            : /* ---------------------------------------------------------------------- */
    1207                 :            : 
    1208                 :         32 : int umac_delete(struct umac_ctx *ctx)
    1209                 :            : /* Deallocate the ctx structure */
    1210                 :            : {
    1211         [ +  - ]:         32 :     if (ctx) {
    1212                 :            :         if (ALLOC_BOUNDARY)
    1213                 :         32 :             ctx = (struct umac_ctx *)ctx->free_ptr;
    1214                 :         32 :         free(ctx);
    1215                 :            :     }
    1216                 :         32 :     return (1);
    1217                 :            : }
    1218                 :            : 
    1219                 :            : /* ---------------------------------------------------------------------- */
    1220                 :            : 
    1221                 :        382 : struct umac_ctx *umac_new(const u_char key[])
    1222                 :            : /* Dynamically allocate a umac_ctx struct, initialize variables, 
    1223                 :            :  * generate subkeys from key. Align to 16-byte boundary.
    1224                 :            :  */
    1225                 :            : {
    1226                 :            :     struct umac_ctx *ctx, *octx;
    1227                 :            :     size_t bytes_to_add;
    1228                 :            :     aes_int_key prf_key;
    1229                 :            :     
    1230                 :        382 :     octx = ctx = xcalloc(1, sizeof(*ctx) + ALLOC_BOUNDARY);
    1231         [ +  - ]:        382 :     if (ctx) {
    1232                 :            :         if (ALLOC_BOUNDARY) {
    1233                 :        382 :             bytes_to_add = ALLOC_BOUNDARY -
    1234                 :        382 :                               ((ptrdiff_t)ctx & (ALLOC_BOUNDARY - 1));
    1235                 :        382 :             ctx = (struct umac_ctx *)((u_char *)ctx + bytes_to_add);
    1236                 :            :         }
    1237                 :        382 :         ctx->free_ptr = octx;
    1238                 :        382 :         aes_key_setup(key, prf_key);
    1239                 :        382 :         pdf_init(&ctx->pdf, prf_key);
    1240                 :        382 :         uhash_init(&ctx->hash, prf_key);
    1241                 :            :     }
    1242                 :            :         
    1243                 :        382 :     return (ctx);
    1244                 :            : }
    1245                 :            : 
    1246                 :            : /* ---------------------------------------------------------------------- */
    1247                 :            : 
    1248                 :       2152 : int umac_final(struct umac_ctx *ctx, u_char tag[], const u_char nonce[8])
    1249                 :            : /* Incorporate any pending data, pad, and generate tag */
    1250                 :            : {
    1251                 :       2152 :     uhash_final(&ctx->hash, (u_char *)tag);
    1252                 :       2152 :     pdf_gen_xor(&ctx->pdf, (const UINT8 *)nonce, (UINT8 *)tag);
    1253                 :            :     
    1254                 :       2152 :     return (1);
    1255                 :            : }
    1256                 :            : 
    1257                 :            : /* ---------------------------------------------------------------------- */
    1258                 :            : 
    1259                 :       2152 : int umac_update(struct umac_ctx *ctx, const u_char *input, long len)
    1260                 :            : /* Given len bytes of data, we parse it into L1_KEY_LEN chunks and   */
    1261                 :            : /* hash each one, calling the PDF on the hashed output whenever the hash- */
    1262                 :            : /* output buffer is full.                                                 */
    1263                 :            : {
    1264                 :       2152 :     uhash_update(&ctx->hash, input, len);
    1265                 :       2152 :     return (1);
    1266                 :            : }
    1267                 :            : 
    1268                 :            : /* ---------------------------------------------------------------------- */
    1269                 :            : 
    1270                 :            : #if 0
    1271                 :            : int umac(struct umac_ctx *ctx, u_char *input, 
    1272                 :            :          long len, u_char tag[],
    1273                 :            :          u_char nonce[8])
    1274                 :            : /* All-in-one version simply calls umac_update() and umac_final().        */
    1275                 :            : {
    1276                 :            :     uhash(&ctx->hash, input, len, (u_char *)tag);
    1277                 :            :     pdf_gen_xor(&ctx->pdf, (UINT8 *)nonce, (UINT8 *)tag);
    1278                 :            :     
    1279                 :            :     return (1);
    1280                 :            : }
    1281                 :            : #endif
    1282                 :            : 
    1283                 :            : /* ---------------------------------------------------------------------- */
    1284                 :            : /* ---------------------------------------------------------------------- */
    1285                 :            : /* ----- End UMAC Section ----------------------------------------------- */
    1286                 :            : /* ---------------------------------------------------------------------- */
    1287                 :            : /* ---------------------------------------------------------------------- */

Generated by: LCOV version 1.9