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