Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/openssh/src/umac.c |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||
---|---|---|---|---|---|---|---|---|
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 */ | - | ||||||
90 | typedef u_int8_t UINT8; /* 1 byte */ | - | ||||||
91 | typedef u_int16_t UINT16; /* 2 byte */ | - | ||||||
92 | typedef u_int32_t UINT32; /* 4 byte */ | - | ||||||
93 | typedef u_int64_t UINT64; /* 8 bytes */ | - | ||||||
94 | typedef 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 | - | ||||||
162 | typedef 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) | - | ||||||
170 | typedef 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 | */ | - | ||||||
184 | static 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) {
| 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) {
| 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 | - | |||||||
216 | typedef 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 | - | |||||||
222 | static 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 | - | |||||||
235 | static 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]) ||
| 0 | ||||||
260 | (((const UINT32 *)nonce)[0] != ((UINT32 *)pc->nonce)[0]) )
| 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 | - | |||||||
319 | typedef 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 | - | |||||||
330 | static 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 | - | |||||||
365 | static 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 | - | |||||||
412 | static 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 | - | |||||||
467 | static 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
| 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 | - | |||||||
536 | static 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__) | - | ||||||
552 | static 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) {
| 0 | ||||||
558 | UINT32 *p = (UINT32 *)buf; | - | ||||||
559 | do { | - | ||||||
560 | *p = LOAD_UINT32_REVERSED(p); | - | ||||||
561 | p++; | - | ||||||
562 | } while (--iters); never executed: end of block
| 0 | ||||||
563 | } else if (bpw == 8) { never executed: end of block
| 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
| 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 | - | |||||||
581 | static 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 | - | |||||||
601 | static 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 | - | |||||||
611 | static 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) {
| 0 | ||||||
619 | if (j) {
| 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) {
| 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 | - | |||||||
642 | static void zero_pad(UINT8 *p, int nbytes) | - | ||||||
643 | { | - | ||||||
644 | /* Write "nbytes" of zeroes, beginning at "p" */ | - | ||||||
645 | if (nbytes >= (int)sizeof(UWORD)) {
| 0 | ||||||
646 | while ((ptrdiff_t)p % sizeof(UWORD)) {
| 0 | ||||||
647 | *p = 0; | - | ||||||
648 | nbytes--; | - | ||||||
649 | p++; | - | ||||||
650 | } never executed: end of block | 0 | ||||||
651 | while (nbytes >= (int)sizeof(UWORD)) {
| 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) {
| 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 | - | |||||||
666 | static 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) {
| 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
| 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 | - | |||||||
706 | static 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 | - | |||||||
774 | typedef 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; | - | ||||||
783 | typedef 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 | - | |||||||
796 | static 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)
| 0 | ||||||
815 | res += 59; never executed: res += 59; | 0 | ||||||
816 | - | |||||||
817 | res += data; | - | ||||||
818 | if (res < data)
| 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 | */ | - | ||||||
831 | static 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++) {
| 0 | ||||||
837 | if ((UINT32)(data[i] >> 32) == 0xfffffffful) {
| 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 | - | |||||||
859 | static 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 | - | |||||||
869 | static 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)
| 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 | */ | - | ||||||
887 | static 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 | */ | - | ||||||
912 | static 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++) {
| 0 | ||||||
918 | /* fix polyhash output not in Z_p64 */ | - | ||||||
919 | if (ahc->poly_accum[i] >= p64)
| 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 */ | - | ||||||
933 | static 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 | */ | - | ||||||
957 | static 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++) {
| 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++)
| 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++)
| 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 | - | ||||||
1003 | static 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 | - | ||||||
1028 | static 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 | - | |||||||
1045 | static 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) {
| 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)
| 0 | ||||||
1061 | bytes_hashed = L1_KEY_LEN; never executed: bytes_hashed = 1024; | 0 | ||||||
1062 | - | |||||||
1063 | if (bytes_hashed + len >= L1_KEY_LEN) {
| 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) {
| 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) {
| 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) {
| 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 | - | |||||||
1101 | static 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) {
| 0 | ||||||
1108 | if (ctx->msg_len % L1_KEY_LEN) {
| 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 | - | ||||||
1124 | static 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 | */ | - | ||||||
1182 | struct 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 | - | ||||||
1191 | int 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 | - | |||||||
1201 | int umac_delete(struct umac_ctx *ctx) | - | ||||||
1202 | /* Deallocate the ctx structure */ | - | ||||||
1203 | { | - | ||||||
1204 | if (ctx) {
| 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 | - | |||||||
1215 | struct 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) {
| 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 | - | |||||||
1243 | int 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 | - | |||||||
1254 | int 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 | - | ||||||
1266 | int 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 code | Switch to Preprocessed file |