OpenCoverage

umac.c #2

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

Generated by Squish Coco 4.2.2