1392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* ====================================================================
2392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * Copyright (c) 2010 The OpenSSL Project.  All rights reserved.
3392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
4392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * Redistribution and use in source and binary forms, with or without
5392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * modification, are permitted provided that the following conditions
6392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * are met:
7392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
8392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 1. Redistributions of source code must retain the above copyright
9392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    notice, this list of conditions and the following disclaimer.
10392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
11392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 2. Redistributions in binary form must reproduce the above copyright
12392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    notice, this list of conditions and the following disclaimer in
13392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    the documentation and/or other materials provided with the
14392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    distribution.
15392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
16392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 3. All advertising materials mentioning features or use of this
17392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    software must display the following acknowledgment:
18392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    "This product includes software developed by the OpenSSL Project
19392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
20392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
21392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    endorse or promote products derived from this software without
23392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    prior written permission. For written permission, please contact
24392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    openssl-core@openssl.org.
25392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
26392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 5. Products derived from this software may not be called "OpenSSL"
27392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    nor may "OpenSSL" appear in their names without prior written
28392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    permission of the OpenSSL Project.
29392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
30392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 6. Redistributions of any form whatsoever must retain the following
31392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    acknowledgment:
32392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    "This product includes software developed by the OpenSSL Project
33392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
34392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
35392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
39392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * OF THE POSSIBILITY OF SUCH DAMAGE.
47392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * ====================================================================
48392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom */
49392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
50392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define OPENSSL_FIPSAPI
51392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
52392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#include <openssl/crypto.h>
53392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#include "modes_lcl.h"
54392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#include <string.h>
55392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
56392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifndef MODES_DEBUG
57392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# ifndef NDEBUG
58392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#  define NDEBUG
59392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# endif
60392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
61392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#include <assert.h>
62392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
63392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(BSWAP4) && defined(STRICT_ALIGNMENT)
64392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* redefine, because alignment is ensured */
65392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#undef	GETU32
66392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define	GETU32(p)	BSWAP4(*(const u32 *)(p))
67392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#undef	PUTU32
68392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define	PUTU32(p,v)	*(u32 *)(p) = BSWAP4(v)
69392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
70392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
71392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define	PACK(s)		((size_t)(s)<<(sizeof(size_t)*8-16))
72392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define REDUCE1BIT(V)	do { \
73392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (sizeof(size_t)==8) { \
74392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		u64 T = U64(0xe100000000000000) & (0-(V.lo&1)); \
75392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		V.lo  = (V.hi<<63)|(V.lo>>1); \
76392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		V.hi  = (V.hi>>1 )^T; \
77392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	} \
78392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else { \
79392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		u32 T = 0xe1000000U & (0-(u32)(V.lo&1)); \
80392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		V.lo  = (V.hi<<63)|(V.lo>>1); \
81392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		V.hi  = (V.hi>>1 )^((u64)T<<32); \
82392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	} \
83392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom} while(0)
84392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
85392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/*
86392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * Even though permitted values for TABLE_BITS are 8, 4 and 1, it should
87392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * never be set to 8. 8 is effectively reserved for testing purposes.
88392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * TABLE_BITS>1 are lookup-table-driven implementations referred to as
89392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * "Shoup's" in GCM specification. In other words OpenSSL does not cover
90392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * whole spectrum of possible table driven implementations. Why? In
91392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * non-"Shoup's" case memory access pattern is segmented in such manner,
92392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * that it's trivial to see that cache timing information can reveal
93392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * fair portion of intermediate hash value. Given that ciphertext is
94392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * always available to attacker, it's possible for him to attempt to
95392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * deduce secret parameter H and if successful, tamper with messages
96392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * [which is nothing but trivial in CTR mode]. In "Shoup's" case it's
97392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * not as trivial, but there is no reason to believe that it's resistant
98392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * to cache-timing attack. And the thing about "8-bit" implementation is
99392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * that it consumes 16 (sixteen) times more memory, 4KB per individual
100392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * key + 1KB shared. Well, on pros side it should be twice as fast as
101392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * "4-bit" version. And for gcc-generated x86[_64] code, "8-bit" version
102392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * was observed to run ~75% faster, closer to 100% for commercial
103392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * compilers... Yet "4-bit" procedure is preferred, because it's
104392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * believed to provide better security-performance balance and adequate
105392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * all-round performance. "All-round" refers to things like:
106392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
107392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * - shorter setup time effectively improves overall timing for
108392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *   handling short messages;
109392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * - larger table allocation can become unbearable because of VM
110392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *   subsystem penalties (for example on Windows large enough free
111392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *   results in VM working set trimming, meaning that consequent
112392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *   malloc would immediately incur working set expansion);
113392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * - larger table has larger cache footprint, which can affect
114392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *   performance of other code paths (not necessarily even from same
115392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *   thread in Hyper-Threading world);
116392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
117392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * Value of 1 is not appropriate for performance reasons.
118392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom */
119392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if	TABLE_BITS==8
120392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
121392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic void gcm_init_8bit(u128 Htable[256], u64 H[2])
122392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
123392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int  i, j;
124392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	u128 V;
125392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
126392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Htable[0].hi = 0;
127392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Htable[0].lo = 0;
128392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	V.hi = H[0];
129392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	V.lo = H[1];
130392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
131392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	for (Htable[128]=V, i=64; i>0; i>>=1) {
132392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		REDUCE1BIT(V);
133392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Htable[i] = V;
134392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
135392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
136392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	for (i=2; i<256; i<<=1) {
137392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		u128 *Hi = Htable+i, H0 = *Hi;
138392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		for (j=1; j<i; ++j) {
139392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			Hi[j].hi = H0.hi^Htable[j].hi;
140392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			Hi[j].lo = H0.lo^Htable[j].lo;
141392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
142392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
143392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
144392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
145392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic void gcm_gmult_8bit(u64 Xi[2], const u128 Htable[256])
146392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
147392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	u128 Z = { 0, 0};
148392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	const u8 *xi = (const u8 *)Xi+15;
149392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	size_t rem, n = *xi;
150392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	const union { long one; char little; } is_endian = {1};
151392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	static const size_t rem_8bit[256] = {
152392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x0000), PACK(0x01C2), PACK(0x0384), PACK(0x0246),
153392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x0708), PACK(0x06CA), PACK(0x048C), PACK(0x054E),
154392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x0E10), PACK(0x0FD2), PACK(0x0D94), PACK(0x0C56),
155392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x0918), PACK(0x08DA), PACK(0x0A9C), PACK(0x0B5E),
156392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x1C20), PACK(0x1DE2), PACK(0x1FA4), PACK(0x1E66),
157392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x1B28), PACK(0x1AEA), PACK(0x18AC), PACK(0x196E),
158392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x1230), PACK(0x13F2), PACK(0x11B4), PACK(0x1076),
159392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x1538), PACK(0x14FA), PACK(0x16BC), PACK(0x177E),
160392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x3840), PACK(0x3982), PACK(0x3BC4), PACK(0x3A06),
161392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x3F48), PACK(0x3E8A), PACK(0x3CCC), PACK(0x3D0E),
162392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x3650), PACK(0x3792), PACK(0x35D4), PACK(0x3416),
163392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x3158), PACK(0x309A), PACK(0x32DC), PACK(0x331E),
164392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x2460), PACK(0x25A2), PACK(0x27E4), PACK(0x2626),
165392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x2368), PACK(0x22AA), PACK(0x20EC), PACK(0x212E),
166392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x2A70), PACK(0x2BB2), PACK(0x29F4), PACK(0x2836),
167392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x2D78), PACK(0x2CBA), PACK(0x2EFC), PACK(0x2F3E),
168392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x7080), PACK(0x7142), PACK(0x7304), PACK(0x72C6),
169392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x7788), PACK(0x764A), PACK(0x740C), PACK(0x75CE),
170392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x7E90), PACK(0x7F52), PACK(0x7D14), PACK(0x7CD6),
171392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x7998), PACK(0x785A), PACK(0x7A1C), PACK(0x7BDE),
172392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x6CA0), PACK(0x6D62), PACK(0x6F24), PACK(0x6EE6),
173392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x6BA8), PACK(0x6A6A), PACK(0x682C), PACK(0x69EE),
174392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x62B0), PACK(0x6372), PACK(0x6134), PACK(0x60F6),
175392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x65B8), PACK(0x647A), PACK(0x663C), PACK(0x67FE),
176392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x48C0), PACK(0x4902), PACK(0x4B44), PACK(0x4A86),
177392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x4FC8), PACK(0x4E0A), PACK(0x4C4C), PACK(0x4D8E),
178392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x46D0), PACK(0x4712), PACK(0x4554), PACK(0x4496),
179392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x41D8), PACK(0x401A), PACK(0x425C), PACK(0x439E),
180392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x54E0), PACK(0x5522), PACK(0x5764), PACK(0x56A6),
181392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x53E8), PACK(0x522A), PACK(0x506C), PACK(0x51AE),
182392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x5AF0), PACK(0x5B32), PACK(0x5974), PACK(0x58B6),
183392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x5DF8), PACK(0x5C3A), PACK(0x5E7C), PACK(0x5FBE),
184392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0xE100), PACK(0xE0C2), PACK(0xE284), PACK(0xE346),
185392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0xE608), PACK(0xE7CA), PACK(0xE58C), PACK(0xE44E),
186392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0xEF10), PACK(0xEED2), PACK(0xEC94), PACK(0xED56),
187392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0xE818), PACK(0xE9DA), PACK(0xEB9C), PACK(0xEA5E),
188392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0xFD20), PACK(0xFCE2), PACK(0xFEA4), PACK(0xFF66),
189392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0xFA28), PACK(0xFBEA), PACK(0xF9AC), PACK(0xF86E),
190392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0xF330), PACK(0xF2F2), PACK(0xF0B4), PACK(0xF176),
191392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0xF438), PACK(0xF5FA), PACK(0xF7BC), PACK(0xF67E),
192392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0xD940), PACK(0xD882), PACK(0xDAC4), PACK(0xDB06),
193392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0xDE48), PACK(0xDF8A), PACK(0xDDCC), PACK(0xDC0E),
194392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0xD750), PACK(0xD692), PACK(0xD4D4), PACK(0xD516),
195392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0xD058), PACK(0xD19A), PACK(0xD3DC), PACK(0xD21E),
196392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0xC560), PACK(0xC4A2), PACK(0xC6E4), PACK(0xC726),
197392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0xC268), PACK(0xC3AA), PACK(0xC1EC), PACK(0xC02E),
198392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0xCB70), PACK(0xCAB2), PACK(0xC8F4), PACK(0xC936),
199392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0xCC78), PACK(0xCDBA), PACK(0xCFFC), PACK(0xCE3E),
200392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x9180), PACK(0x9042), PACK(0x9204), PACK(0x93C6),
201392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x9688), PACK(0x974A), PACK(0x950C), PACK(0x94CE),
202392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x9F90), PACK(0x9E52), PACK(0x9C14), PACK(0x9DD6),
203392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x9898), PACK(0x995A), PACK(0x9B1C), PACK(0x9ADE),
204392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x8DA0), PACK(0x8C62), PACK(0x8E24), PACK(0x8FE6),
205392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x8AA8), PACK(0x8B6A), PACK(0x892C), PACK(0x88EE),
206392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x83B0), PACK(0x8272), PACK(0x8034), PACK(0x81F6),
207392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0x84B8), PACK(0x857A), PACK(0x873C), PACK(0x86FE),
208392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0xA9C0), PACK(0xA802), PACK(0xAA44), PACK(0xAB86),
209392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0xAEC8), PACK(0xAF0A), PACK(0xAD4C), PACK(0xAC8E),
210392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0xA7D0), PACK(0xA612), PACK(0xA454), PACK(0xA596),
211392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0xA0D8), PACK(0xA11A), PACK(0xA35C), PACK(0xA29E),
212392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0xB5E0), PACK(0xB422), PACK(0xB664), PACK(0xB7A6),
213392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0xB2E8), PACK(0xB32A), PACK(0xB16C), PACK(0xB0AE),
214392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0xBBF0), PACK(0xBA32), PACK(0xB874), PACK(0xB9B6),
215392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PACK(0xBCF8), PACK(0xBD3A), PACK(0xBF7C), PACK(0xBEBE) };
216392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
217392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	while (1) {
218392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.hi ^= Htable[n].hi;
219392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.lo ^= Htable[n].lo;
220392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
221392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if ((u8 *)Xi==xi)	break;
222392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
223392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		n = *(--xi);
224392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
225392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		rem  = (size_t)Z.lo&0xff;
226392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.lo = (Z.hi<<56)|(Z.lo>>8);
227392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.hi = (Z.hi>>8);
228392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (sizeof(size_t)==8)
229392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			Z.hi ^= rem_8bit[rem];
230392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
231392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			Z.hi ^= (u64)rem_8bit[rem]<<32;
232392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
233392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
234392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (is_endian.little) {
235392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef BSWAP8
236392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Xi[0] = BSWAP8(Z.hi);
237392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Xi[1] = BSWAP8(Z.lo);
238392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
239392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		u8 *p = (u8 *)Xi;
240392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		u32 v;
241392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		v = (u32)(Z.hi>>32);	PUTU32(p,v);
242392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		v = (u32)(Z.hi);	PUTU32(p+4,v);
243392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		v = (u32)(Z.lo>>32);	PUTU32(p+8,v);
244392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		v = (u32)(Z.lo);	PUTU32(p+12,v);
245392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
246392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
247392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else {
248392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Xi[0] = Z.hi;
249392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Xi[1] = Z.lo;
250392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
251392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
252392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define GCM_MUL(ctx,Xi)   gcm_gmult_8bit(ctx->Xi.u,ctx->Htable)
253392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
254392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#elif	TABLE_BITS==4
255392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
256392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic void gcm_init_4bit(u128 Htable[16], u64 H[2])
257392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
258392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	u128 V;
259392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(OPENSSL_SMALL_FOOTPRINT)
260392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int  i;
261392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
262392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
263392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Htable[0].hi = 0;
264392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Htable[0].lo = 0;
265392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	V.hi = H[0];
266392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	V.lo = H[1];
267392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
268392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(OPENSSL_SMALL_FOOTPRINT)
269392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	for (Htable[8]=V, i=4; i>0; i>>=1) {
270392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		REDUCE1BIT(V);
271392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Htable[i] = V;
272392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
273392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
274392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	for (i=2; i<16; i<<=1) {
275392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		u128 *Hi = Htable+i;
276392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		int   j;
277392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		for (V=*Hi, j=1; j<i; ++j) {
278392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			Hi[j].hi = V.hi^Htable[j].hi;
279392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			Hi[j].lo = V.lo^Htable[j].lo;
280392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
281392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
282392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
283392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Htable[8] = V;
284392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	REDUCE1BIT(V);
285392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Htable[4] = V;
286392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	REDUCE1BIT(V);
287392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Htable[2] = V;
288392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	REDUCE1BIT(V);
289392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Htable[1] = V;
290392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Htable[3].hi  = V.hi^Htable[2].hi, Htable[3].lo  = V.lo^Htable[2].lo;
291392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	V=Htable[4];
292392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Htable[5].hi  = V.hi^Htable[1].hi, Htable[5].lo  = V.lo^Htable[1].lo;
293392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Htable[6].hi  = V.hi^Htable[2].hi, Htable[6].lo  = V.lo^Htable[2].lo;
294392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Htable[7].hi  = V.hi^Htable[3].hi, Htable[7].lo  = V.lo^Htable[3].lo;
295392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	V=Htable[8];
296392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Htable[9].hi  = V.hi^Htable[1].hi, Htable[9].lo  = V.lo^Htable[1].lo;
297392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Htable[10].hi = V.hi^Htable[2].hi, Htable[10].lo = V.lo^Htable[2].lo;
298392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Htable[11].hi = V.hi^Htable[3].hi, Htable[11].lo = V.lo^Htable[3].lo;
299392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Htable[12].hi = V.hi^Htable[4].hi, Htable[12].lo = V.lo^Htable[4].lo;
300392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Htable[13].hi = V.hi^Htable[5].hi, Htable[13].lo = V.lo^Htable[5].lo;
301392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Htable[14].hi = V.hi^Htable[6].hi, Htable[14].lo = V.lo^Htable[6].lo;
302392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Htable[15].hi = V.hi^Htable[7].hi, Htable[15].lo = V.lo^Htable[7].lo;
303392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
304392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(GHASH_ASM) && (defined(__arm__) || defined(__arm))
305392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/*
306392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	 * ARM assembler expects specific dword order in Htable.
307392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	 */
308392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
309392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int j;
310392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	const union { long one; char little; } is_endian = {1};
311392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
312392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (is_endian.little)
313392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		for (j=0;j<16;++j) {
314392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			V = Htable[j];
315392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			Htable[j].hi = V.lo;
316392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			Htable[j].lo = V.hi;
317392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
318392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else
319392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		for (j=0;j<16;++j) {
320392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			V = Htable[j];
321392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			Htable[j].hi = V.lo<<32|V.lo>>32;
322392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			Htable[j].lo = V.hi<<32|V.hi>>32;
323392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
324392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
325392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
326392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
327392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
328392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifndef GHASH_ASM
329392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const size_t rem_4bit[16] = {
330392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	PACK(0x0000), PACK(0x1C20), PACK(0x3840), PACK(0x2460),
331392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	PACK(0x7080), PACK(0x6CA0), PACK(0x48C0), PACK(0x54E0),
332392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	PACK(0xE100), PACK(0xFD20), PACK(0xD940), PACK(0xC560),
333392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	PACK(0x9180), PACK(0x8DA0), PACK(0xA9C0), PACK(0xB5E0) };
334392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
335392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic void gcm_gmult_4bit(u64 Xi[2], const u128 Htable[16])
336392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
337392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	u128 Z;
338392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int cnt = 15;
339392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	size_t rem, nlo, nhi;
340392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	const union { long one; char little; } is_endian = {1};
341392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
342392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	nlo  = ((const u8 *)Xi)[15];
343392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	nhi  = nlo>>4;
344392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	nlo &= 0xf;
345392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
346392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Z.hi = Htable[nlo].hi;
347392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Z.lo = Htable[nlo].lo;
348392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
349392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	while (1) {
350392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		rem  = (size_t)Z.lo&0xf;
351392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.lo = (Z.hi<<60)|(Z.lo>>4);
352392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.hi = (Z.hi>>4);
353392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (sizeof(size_t)==8)
354392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			Z.hi ^= rem_4bit[rem];
355392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
356392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			Z.hi ^= (u64)rem_4bit[rem]<<32;
357392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
358392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.hi ^= Htable[nhi].hi;
359392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.lo ^= Htable[nhi].lo;
360392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
361392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (--cnt<0)		break;
362392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
363392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		nlo  = ((const u8 *)Xi)[cnt];
364392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		nhi  = nlo>>4;
365392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		nlo &= 0xf;
366392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
367392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		rem  = (size_t)Z.lo&0xf;
368392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.lo = (Z.hi<<60)|(Z.lo>>4);
369392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.hi = (Z.hi>>4);
370392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (sizeof(size_t)==8)
371392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			Z.hi ^= rem_4bit[rem];
372392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
373392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			Z.hi ^= (u64)rem_4bit[rem]<<32;
374392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
375392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.hi ^= Htable[nlo].hi;
376392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.lo ^= Htable[nlo].lo;
377392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
378392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
379392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (is_endian.little) {
380392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef BSWAP8
381392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Xi[0] = BSWAP8(Z.hi);
382392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Xi[1] = BSWAP8(Z.lo);
383392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
384392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		u8 *p = (u8 *)Xi;
385392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		u32 v;
386392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		v = (u32)(Z.hi>>32);	PUTU32(p,v);
387392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		v = (u32)(Z.hi);	PUTU32(p+4,v);
388392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		v = (u32)(Z.lo>>32);	PUTU32(p+8,v);
389392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		v = (u32)(Z.lo);	PUTU32(p+12,v);
390392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
391392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
392392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else {
393392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Xi[0] = Z.hi;
394392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Xi[1] = Z.lo;
395392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
396392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
397392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
398392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if !defined(OPENSSL_SMALL_FOOTPRINT)
399392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/*
400392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * Streamed gcm_mult_4bit, see CRYPTO_gcm128_[en|de]crypt for
401392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * details... Compiler-generated code doesn't seem to give any
402392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * performance improvement, at least not on x86[_64]. It's here
403392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * mostly as reference and a placeholder for possible future
404392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * non-trivial optimization[s]...
405392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom */
406392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic void gcm_ghash_4bit(u64 Xi[2],const u128 Htable[16],
407392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				const u8 *inp,size_t len)
408392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
409392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom    u128 Z;
410392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom    int cnt;
411392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom    size_t rem, nlo, nhi;
412392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom    const union { long one; char little; } is_endian = {1};
413392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
414392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if 1
415392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom    do {
416392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	cnt  = 15;
417392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	nlo  = ((const u8 *)Xi)[15];
418392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	nlo ^= inp[15];
419392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	nhi  = nlo>>4;
420392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	nlo &= 0xf;
421392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
422392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Z.hi = Htable[nlo].hi;
423392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Z.lo = Htable[nlo].lo;
424392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
425392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	while (1) {
426392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		rem  = (size_t)Z.lo&0xf;
427392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.lo = (Z.hi<<60)|(Z.lo>>4);
428392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.hi = (Z.hi>>4);
429392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (sizeof(size_t)==8)
430392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			Z.hi ^= rem_4bit[rem];
431392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
432392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			Z.hi ^= (u64)rem_4bit[rem]<<32;
433392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
434392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.hi ^= Htable[nhi].hi;
435392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.lo ^= Htable[nhi].lo;
436392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
437392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (--cnt<0)		break;
438392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
439392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		nlo  = ((const u8 *)Xi)[cnt];
440392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		nlo ^= inp[cnt];
441392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		nhi  = nlo>>4;
442392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		nlo &= 0xf;
443392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
444392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		rem  = (size_t)Z.lo&0xf;
445392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.lo = (Z.hi<<60)|(Z.lo>>4);
446392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.hi = (Z.hi>>4);
447392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (sizeof(size_t)==8)
448392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			Z.hi ^= rem_4bit[rem];
449392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
450392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			Z.hi ^= (u64)rem_4bit[rem]<<32;
451392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
452392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.hi ^= Htable[nlo].hi;
453392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.lo ^= Htable[nlo].lo;
454392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
455392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
456392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom    /*
457392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom     * Extra 256+16 bytes per-key plus 512 bytes shared tables
458392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom     * [should] give ~50% improvement... One could have PACK()-ed
459392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom     * the rem_8bit even here, but the priority is to minimize
460392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom     * cache footprint...
461392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom     */
462392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom    u128 Hshr4[16];	/* Htable shifted right by 4 bits */
463392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom    u8   Hshl4[16];	/* Htable shifted left  by 4 bits */
464392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom    static const unsigned short rem_8bit[256] = {
465392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0x0000, 0x01C2, 0x0384, 0x0246, 0x0708, 0x06CA, 0x048C, 0x054E,
466392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0x0E10, 0x0FD2, 0x0D94, 0x0C56, 0x0918, 0x08DA, 0x0A9C, 0x0B5E,
467392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0x1C20, 0x1DE2, 0x1FA4, 0x1E66, 0x1B28, 0x1AEA, 0x18AC, 0x196E,
468392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0x1230, 0x13F2, 0x11B4, 0x1076, 0x1538, 0x14FA, 0x16BC, 0x177E,
469392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0x3840, 0x3982, 0x3BC4, 0x3A06, 0x3F48, 0x3E8A, 0x3CCC, 0x3D0E,
470392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0x3650, 0x3792, 0x35D4, 0x3416, 0x3158, 0x309A, 0x32DC, 0x331E,
471392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0x2460, 0x25A2, 0x27E4, 0x2626, 0x2368, 0x22AA, 0x20EC, 0x212E,
472392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0x2A70, 0x2BB2, 0x29F4, 0x2836, 0x2D78, 0x2CBA, 0x2EFC, 0x2F3E,
473392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0x7080, 0x7142, 0x7304, 0x72C6, 0x7788, 0x764A, 0x740C, 0x75CE,
474392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0x7E90, 0x7F52, 0x7D14, 0x7CD6, 0x7998, 0x785A, 0x7A1C, 0x7BDE,
475392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0x6CA0, 0x6D62, 0x6F24, 0x6EE6, 0x6BA8, 0x6A6A, 0x682C, 0x69EE,
476392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0x62B0, 0x6372, 0x6134, 0x60F6, 0x65B8, 0x647A, 0x663C, 0x67FE,
477392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0x48C0, 0x4902, 0x4B44, 0x4A86, 0x4FC8, 0x4E0A, 0x4C4C, 0x4D8E,
478392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0x46D0, 0x4712, 0x4554, 0x4496, 0x41D8, 0x401A, 0x425C, 0x439E,
479392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0x54E0, 0x5522, 0x5764, 0x56A6, 0x53E8, 0x522A, 0x506C, 0x51AE,
480392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0x5AF0, 0x5B32, 0x5974, 0x58B6, 0x5DF8, 0x5C3A, 0x5E7C, 0x5FBE,
481392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0xE100, 0xE0C2, 0xE284, 0xE346, 0xE608, 0xE7CA, 0xE58C, 0xE44E,
482392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0xEF10, 0xEED2, 0xEC94, 0xED56, 0xE818, 0xE9DA, 0xEB9C, 0xEA5E,
483392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0xFD20, 0xFCE2, 0xFEA4, 0xFF66, 0xFA28, 0xFBEA, 0xF9AC, 0xF86E,
484392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0xF330, 0xF2F2, 0xF0B4, 0xF176, 0xF438, 0xF5FA, 0xF7BC, 0xF67E,
485392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0xD940, 0xD882, 0xDAC4, 0xDB06, 0xDE48, 0xDF8A, 0xDDCC, 0xDC0E,
486392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0xD750, 0xD692, 0xD4D4, 0xD516, 0xD058, 0xD19A, 0xD3DC, 0xD21E,
487392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0xC560, 0xC4A2, 0xC6E4, 0xC726, 0xC268, 0xC3AA, 0xC1EC, 0xC02E,
488392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0xCB70, 0xCAB2, 0xC8F4, 0xC936, 0xCC78, 0xCDBA, 0xCFFC, 0xCE3E,
489392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0x9180, 0x9042, 0x9204, 0x93C6, 0x9688, 0x974A, 0x950C, 0x94CE,
490392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0x9F90, 0x9E52, 0x9C14, 0x9DD6, 0x9898, 0x995A, 0x9B1C, 0x9ADE,
491392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0x8DA0, 0x8C62, 0x8E24, 0x8FE6, 0x8AA8, 0x8B6A, 0x892C, 0x88EE,
492392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0x83B0, 0x8272, 0x8034, 0x81F6, 0x84B8, 0x857A, 0x873C, 0x86FE,
493392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0xA9C0, 0xA802, 0xAA44, 0xAB86, 0xAEC8, 0xAF0A, 0xAD4C, 0xAC8E,
494392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0xA7D0, 0xA612, 0xA454, 0xA596, 0xA0D8, 0xA11A, 0xA35C, 0xA29E,
495392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0xB5E0, 0xB422, 0xB664, 0xB7A6, 0xB2E8, 0xB32A, 0xB16C, 0xB0AE,
496392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	0xBBF0, 0xBA32, 0xB874, 0xB9B6, 0xBCF8, 0xBD3A, 0xBF7C, 0xBEBE };
497392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom    /*
498392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom     * This pre-processing phase slows down procedure by approximately
499392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom     * same time as it makes each loop spin faster. In other words
500392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom     * single block performance is approximately same as straightforward
501392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom     * "4-bit" implementation, and then it goes only faster...
502392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom     */
503392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom    for (cnt=0; cnt<16; ++cnt) {
504392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Z.hi = Htable[cnt].hi;
505392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Z.lo = Htable[cnt].lo;
506392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Hshr4[cnt].lo = (Z.hi<<60)|(Z.lo>>4);
507392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Hshr4[cnt].hi = (Z.hi>>4);
508392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Hshl4[cnt]    = (u8)(Z.lo<<4);
509392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom    }
510392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
511392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom    do {
512392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	for (Z.lo=0, Z.hi=0, cnt=15; cnt; --cnt) {
513392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		nlo  = ((const u8 *)Xi)[cnt];
514392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		nlo ^= inp[cnt];
515392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		nhi  = nlo>>4;
516392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		nlo &= 0xf;
517392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
518392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.hi ^= Htable[nlo].hi;
519392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.lo ^= Htable[nlo].lo;
520392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
521392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		rem = (size_t)Z.lo&0xff;
522392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
523392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.lo = (Z.hi<<56)|(Z.lo>>8);
524392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.hi = (Z.hi>>8);
525392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
526392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.hi ^= Hshr4[nhi].hi;
527392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.lo ^= Hshr4[nhi].lo;
528392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Z.hi ^= (u64)rem_8bit[rem^Hshl4[nhi]]<<48;
529392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
530392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
531392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	nlo  = ((const u8 *)Xi)[0];
532392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	nlo ^= inp[0];
533392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	nhi  = nlo>>4;
534392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	nlo &= 0xf;
535392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
536392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Z.hi ^= Htable[nlo].hi;
537392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Z.lo ^= Htable[nlo].lo;
538392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
539392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	rem = (size_t)Z.lo&0xf;
540392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
541392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Z.lo = (Z.hi<<60)|(Z.lo>>4);
542392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Z.hi = (Z.hi>>4);
543392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
544392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Z.hi ^= Htable[nhi].hi;
545392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Z.lo ^= Htable[nhi].lo;
546392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	Z.hi ^= ((u64)rem_8bit[rem<<4])<<48;
547392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
548392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
549392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (is_endian.little) {
550392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef BSWAP8
551392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Xi[0] = BSWAP8(Z.hi);
552392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Xi[1] = BSWAP8(Z.lo);
553392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
554392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		u8 *p = (u8 *)Xi;
555392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		u32 v;
556392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		v = (u32)(Z.hi>>32);	PUTU32(p,v);
557392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		v = (u32)(Z.hi);	PUTU32(p+4,v);
558392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		v = (u32)(Z.lo>>32);	PUTU32(p+8,v);
559392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		v = (u32)(Z.lo);	PUTU32(p+12,v);
560392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
561392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
562392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else {
563392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Xi[0] = Z.hi;
564392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Xi[1] = Z.lo;
565392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
566392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom    } while (inp+=16, len-=16);
567392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
568392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
569392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
570392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromvoid gcm_gmult_4bit(u64 Xi[2],const u128 Htable[16]);
571392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromvoid gcm_ghash_4bit(u64 Xi[2],const u128 Htable[16],const u8 *inp,size_t len);
572392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
573392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
574392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define GCM_MUL(ctx,Xi)   gcm_gmult_4bit(ctx->Xi.u,ctx->Htable)
575392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(GHASH_ASM) || !defined(OPENSSL_SMALL_FOOTPRINT)
576392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define GHASH(ctx,in,len) gcm_ghash_4bit((ctx)->Xi.u,(ctx)->Htable,in,len)
577392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* GHASH_CHUNK is "stride parameter" missioned to mitigate cache
578392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * trashing effect. In other words idea is to hash data while it's
579392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * still in L1 cache after encryption pass... */
580392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define GHASH_CHUNK       (3*1024)
581392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
582392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
583392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else	/* TABLE_BITS */
584392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
585392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic void gcm_gmult_1bit(u64 Xi[2],const u64 H[2])
586392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
587392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	u128 V,Z = { 0,0 };
588392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	long X;
589392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int  i,j;
590392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	const long *xi = (const long *)Xi;
591392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	const union { long one; char little; } is_endian = {1};
592392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
593392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	V.hi = H[0];	/* H is in host byte order, no byte swapping */
594392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	V.lo = H[1];
595392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
596392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	for (j=0; j<16/sizeof(long); ++j) {
597392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (is_endian.little) {
598392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (sizeof(long)==8) {
599392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef BSWAP8
600392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				X = (long)(BSWAP8(xi[j]));
601392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
602392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				const u8 *p = (const u8 *)(xi+j);
603392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				X = (long)((u64)GETU32(p)<<32|GETU32(p+4));
604392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
605392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
606392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else {
607392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				const u8 *p = (const u8 *)(xi+j);
608392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				X = (long)GETU32(p);
609392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
610392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
611392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
612392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			X = xi[j];
613392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
614392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		for (i=0; i<8*sizeof(long); ++i, X<<=1) {
615392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			u64 M = (u64)(X>>(8*sizeof(long)-1));
616392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			Z.hi ^= V.hi&M;
617392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			Z.lo ^= V.lo&M;
618392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
619392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			REDUCE1BIT(V);
620392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
621392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
622392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
623392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (is_endian.little) {
624392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef BSWAP8
625392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Xi[0] = BSWAP8(Z.hi);
626392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Xi[1] = BSWAP8(Z.lo);
627392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
628392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		u8 *p = (u8 *)Xi;
629392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		u32 v;
630392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		v = (u32)(Z.hi>>32);	PUTU32(p,v);
631392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		v = (u32)(Z.hi);	PUTU32(p+4,v);
632392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		v = (u32)(Z.lo>>32);	PUTU32(p+8,v);
633392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		v = (u32)(Z.lo);	PUTU32(p+12,v);
634392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
635392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
636392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else {
637392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Xi[0] = Z.hi;
638392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		Xi[1] = Z.lo;
639392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
640392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
641392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define GCM_MUL(ctx,Xi)	  gcm_gmult_1bit(ctx->Xi.u,ctx->H.u)
642392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
643392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
644392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
645392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if	TABLE_BITS==4 && defined(GHASH_ASM)
646392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# if	!defined(I386_ONLY) && \
647392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	(defined(__i386)	|| defined(__i386__)	|| \
648392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	 defined(__x86_64)	|| defined(__x86_64__)	|| \
649392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	 defined(_M_IX86)	|| defined(_M_AMD64)	|| defined(_M_X64))
650392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#  define GHASH_ASM_X86_OR_64
651392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#  define GCM_FUNCREF_4BIT
652392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromextern unsigned int OPENSSL_ia32cap_P[2];
653392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
654392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromvoid gcm_init_clmul(u128 Htable[16],const u64 Xi[2]);
655392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromvoid gcm_gmult_clmul(u64 Xi[2],const u128 Htable[16]);
656392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromvoid gcm_ghash_clmul(u64 Xi[2],const u128 Htable[16],const u8 *inp,size_t len);
657392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
658392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#  if	defined(__i386) || defined(__i386__) || defined(_M_IX86)
659392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#   define GHASH_ASM_X86
660392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromvoid gcm_gmult_4bit_mmx(u64 Xi[2],const u128 Htable[16]);
661392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromvoid gcm_ghash_4bit_mmx(u64 Xi[2],const u128 Htable[16],const u8 *inp,size_t len);
662392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
663392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromvoid gcm_gmult_4bit_x86(u64 Xi[2],const u128 Htable[16]);
664392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromvoid gcm_ghash_4bit_x86(u64 Xi[2],const u128 Htable[16],const u8 *inp,size_t len);
665392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#  endif
666392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# elif defined(__arm__) || defined(__arm)
667392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#  include "arm_arch.h"
668392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#  if __ARM_ARCH__>=7
669392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#   define GHASH_ASM_ARM
670392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#   define GCM_FUNCREF_4BIT
671392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromvoid gcm_gmult_neon(u64 Xi[2],const u128 Htable[16]);
672392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromvoid gcm_ghash_neon(u64 Xi[2],const u128 Htable[16],const u8 *inp,size_t len);
673392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#  endif
674392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# endif
675392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
676392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
677392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef GCM_FUNCREF_4BIT
678392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# undef  GCM_MUL
679392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# define GCM_MUL(ctx,Xi)	(*gcm_gmult_p)(ctx->Xi.u,ctx->Htable)
680392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# ifdef GHASH
681392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#  undef  GHASH
682392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#  define GHASH(ctx,in,len)	(*gcm_ghash_p)(ctx->Xi.u,ctx->Htable,in,len)
683392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# endif
684392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
685392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
686392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromvoid CRYPTO_gcm128_init(GCM128_CONTEXT *ctx,void *key,block128_f block)
687392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
688392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	const union { long one; char little; } is_endian = {1};
689392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
690392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	memset(ctx,0,sizeof(*ctx));
691392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->block = block;
692392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->key   = key;
693392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
694392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	(*block)(ctx->H.c,ctx->H.c,key);
695392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
696392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (is_endian.little) {
697392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* H is stored in host byte order */
698392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef BSWAP8
699392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->H.u[0] = BSWAP8(ctx->H.u[0]);
700392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->H.u[1] = BSWAP8(ctx->H.u[1]);
701392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
702392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		u8 *p = ctx->H.c;
703392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		u64 hi,lo;
704392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		hi = (u64)GETU32(p)  <<32|GETU32(p+4);
705392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		lo = (u64)GETU32(p+8)<<32|GETU32(p+12);
706392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->H.u[0] = hi;
707392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->H.u[1] = lo;
708392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
709392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
710392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
711392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if	TABLE_BITS==8
712392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	gcm_init_8bit(ctx->Htable,ctx->H.u);
713392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#elif	TABLE_BITS==4
714392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# if	defined(GHASH_ASM_X86_OR_64)
715392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#  if	!defined(GHASH_ASM_X86) || defined(OPENSSL_IA32_SSE2)
716392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (OPENSSL_ia32cap_P[0]&(1<<24) &&	/* check FXSR bit */
717392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	    OPENSSL_ia32cap_P[1]&(1<<1) ) {	/* check PCLMULQDQ bit */
718392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		gcm_init_clmul(ctx->Htable,ctx->H.u);
719392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->gmult = gcm_gmult_clmul;
720392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->ghash = gcm_ghash_clmul;
721392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return;
722392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
723392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#  endif
724392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	gcm_init_4bit(ctx->Htable,ctx->H.u);
725392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#  if	defined(GHASH_ASM_X86)			/* x86 only */
72604ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom#   if	defined(OPENSSL_IA32_SSE2)
727392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (OPENSSL_ia32cap_P[0]&(1<<25)) {	/* check SSE bit */
728392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#   else
729392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (OPENSSL_ia32cap_P[0]&(1<<23)) {	/* check MMX bit */
730392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#   endif
731392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->gmult = gcm_gmult_4bit_mmx;
732392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->ghash = gcm_ghash_4bit_mmx;
733392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	} else {
734392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->gmult = gcm_gmult_4bit_x86;
735392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->ghash = gcm_ghash_4bit_x86;
736392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
737392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#  else
738392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->gmult = gcm_gmult_4bit;
739392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->ghash = gcm_ghash_4bit;
740392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#  endif
741392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# elif	defined(GHASH_ASM_ARM)
742392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (OPENSSL_armcap_P & ARMV7_NEON) {
743392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->gmult = gcm_gmult_neon;
744392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->ghash = gcm_ghash_neon;
745392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	} else {
746392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		gcm_init_4bit(ctx->Htable,ctx->H.u);
747392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->gmult = gcm_gmult_4bit;
748392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->ghash = gcm_ghash_4bit;
749392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
750392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# else
751392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	gcm_init_4bit(ctx->Htable,ctx->H.u);
752392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# endif
753392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
754392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
755392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
756392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromvoid CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx,const unsigned char *iv,size_t len)
757392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
758392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	const union { long one; char little; } is_endian = {1};
759392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	unsigned int ctr;
760392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef GCM_FUNCREF_4BIT
761392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*gcm_gmult_p)(u64 Xi[2],const u128 Htable[16])	= ctx->gmult;
762392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
763392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
764392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->Yi.u[0]  = 0;
765392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->Yi.u[1]  = 0;
766392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->Xi.u[0]  = 0;
767392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->Xi.u[1]  = 0;
768392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->len.u[0] = 0;	/* AAD length */
769392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->len.u[1] = 0;	/* message length */
770392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->ares = 0;
771392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->mres = 0;
772392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
773392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (len==12) {
774392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memcpy(ctx->Yi.c,iv,12);
775392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->Yi.c[15]=1;
776392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr=1;
777392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
778392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else {
779392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		size_t i;
780392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		u64 len0 = len;
781392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
782392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while (len>=16) {
783392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			for (i=0; i<16; ++i) ctx->Yi.c[i] ^= iv[i];
784392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			GCM_MUL(ctx,Yi);
785392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			iv += 16;
786392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			len -= 16;
787392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
788392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (len) {
789392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			for (i=0; i<len; ++i) ctx->Yi.c[i] ^= iv[i];
790392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			GCM_MUL(ctx,Yi);
791392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
792392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		len0 <<= 3;
793392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (is_endian.little) {
794392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef BSWAP8
795392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.u[1]  ^= BSWAP8(len0);
796392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
797392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.c[8]  ^= (u8)(len0>>56);
798392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.c[9]  ^= (u8)(len0>>48);
799392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.c[10] ^= (u8)(len0>>40);
800392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.c[11] ^= (u8)(len0>>32);
801392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.c[12] ^= (u8)(len0>>24);
802392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.c[13] ^= (u8)(len0>>16);
803392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.c[14] ^= (u8)(len0>>8);
804392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.c[15] ^= (u8)(len0);
805392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
806392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
807392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
808392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.u[1]  ^= len0;
809392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
810392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		GCM_MUL(ctx,Yi);
811392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
812392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (is_endian.little)
813392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctr = GETU32(ctx->Yi.c+12);
814392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
815392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctr = ctx->Yi.d[3];
816392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
817392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
818392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	(*ctx->block)(ctx->Yi.c,ctx->EK0.c,ctx->key);
819392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	++ctr;
820392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (is_endian.little)
821392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PUTU32(ctx->Yi.c+12,ctr);
822392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else
823392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->Yi.d[3] = ctr;
824392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
825392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
826392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromint CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx,const unsigned char *aad,size_t len)
827392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
828392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	size_t i;
829392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	unsigned int n;
830392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	u64 alen = ctx->len.u[0];
831392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef GCM_FUNCREF_4BIT
832392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*gcm_gmult_p)(u64 Xi[2],const u128 Htable[16])	= ctx->gmult;
833392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# ifdef GHASH
834392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*gcm_ghash_p)(u64 Xi[2],const u128 Htable[16],
835392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				const u8 *inp,size_t len)	= ctx->ghash;
836392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# endif
837392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
838392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
839392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (ctx->len.u[1]) return -2;
840392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
841392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	alen += len;
842392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (alen>(U64(1)<<61) || (sizeof(len)==8 && alen<len))
843392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return -1;
844392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->len.u[0] = alen;
845392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
846392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	n = ctx->ares;
847392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (n) {
848392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while (n && len) {
849392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Xi.c[n] ^= *(aad++);
850392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			--len;
851392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			n = (n+1)%16;
852392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
853392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (n==0) GCM_MUL(ctx,Xi);
854392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else {
855392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->ares = n;
856392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			return 0;
857392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
858392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
859392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
860392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef GHASH
861392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if ((i = (len&(size_t)-16))) {
862392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		GHASH(ctx,aad,i);
863392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		aad += i;
864392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		len -= i;
865392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
866392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
867392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	while (len>=16) {
868392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		for (i=0; i<16; ++i) ctx->Xi.c[i] ^= aad[i];
869392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		GCM_MUL(ctx,Xi);
870392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		aad += 16;
871392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		len -= 16;
872392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
873392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
874392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (len) {
875392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		n = (unsigned int)len;
876392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		for (i=0; i<len; ++i) ctx->Xi.c[i] ^= aad[i];
877392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
878392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
879392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->ares = n;
880392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return 0;
881392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
882392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
883392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromint CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx,
884392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		const unsigned char *in, unsigned char *out,
885392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		size_t len)
886392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
887392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	const union { long one; char little; } is_endian = {1};
888392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	unsigned int n, ctr;
889392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	size_t i;
890392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	u64        mlen  = ctx->len.u[1];
891392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	block128_f block = ctx->block;
892392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void      *key   = ctx->key;
893392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef GCM_FUNCREF_4BIT
894392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*gcm_gmult_p)(u64 Xi[2],const u128 Htable[16])	= ctx->gmult;
895392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# ifdef GHASH
896392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*gcm_ghash_p)(u64 Xi[2],const u128 Htable[16],
897392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				const u8 *inp,size_t len)	= ctx->ghash;
898392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# endif
899392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
900392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
901392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if 0
902392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	n = (unsigned int)mlen%16; /* alternative to ctx->mres */
903392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
904392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	mlen += len;
905392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (mlen>((U64(1)<<36)-32) || (sizeof(len)==8 && mlen<len))
906392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return -1;
907392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->len.u[1] = mlen;
908392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
909392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (ctx->ares) {
910392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* First call to encrypt finalizes GHASH(AAD) */
911392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		GCM_MUL(ctx,Xi);
912392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->ares = 0;
913392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
914392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
915392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (is_endian.little)
916392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr = GETU32(ctx->Yi.c+12);
917392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else
918392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr = ctx->Yi.d[3];
919392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
920392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	n = ctx->mres;
921392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if !defined(OPENSSL_SMALL_FOOTPRINT)
922392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (16%sizeof(size_t) == 0) do {	/* always true actually */
923392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (n) {
924392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			while (n && len) {
925392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Xi.c[n] ^= *(out++) = *(in++)^ctx->EKi.c[n];
926392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				--len;
927392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				n = (n+1)%16;
928392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
929392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (n==0) GCM_MUL(ctx,Xi);
930392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else {
931392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->mres = n;
932392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				return 0;
933392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
934392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
935392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(STRICT_ALIGNMENT)
936392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (((size_t)in|(size_t)out)%sizeof(size_t) != 0)
937392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			break;
938392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
939392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(GHASH) && defined(GHASH_CHUNK)
940392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while (len>=GHASH_CHUNK) {
941392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    size_t j=GHASH_CHUNK;
942392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
943392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    while (j) {
944392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(*block)(ctx->Yi.c,ctx->EKi.c,key);
945392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			++ctr;
946392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (is_endian.little)
947392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				PUTU32(ctx->Yi.c+12,ctr);
948392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
949392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Yi.d[3] = ctr;
950392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			for (i=0; i<16; i+=sizeof(size_t))
951392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				*(size_t *)(out+i) =
952392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				*(size_t *)(in+i)^*(size_t *)(ctx->EKi.c+i);
953392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			out += 16;
954392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			in  += 16;
955392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			j   -= 16;
956392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    }
957392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    GHASH(ctx,out-GHASH_CHUNK,GHASH_CHUNK);
958392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    len -= GHASH_CHUNK;
959392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
960392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if ((i = (len&(size_t)-16))) {
961392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    size_t j=i;
962392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
963392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    while (len>=16) {
964392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(*block)(ctx->Yi.c,ctx->EKi.c,key);
965392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			++ctr;
966392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (is_endian.little)
967392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				PUTU32(ctx->Yi.c+12,ctr);
968392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
969392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Yi.d[3] = ctr;
970392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			for (i=0; i<16; i+=sizeof(size_t))
971392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				*(size_t *)(out+i) =
972392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				*(size_t *)(in+i)^*(size_t *)(ctx->EKi.c+i);
973392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			out += 16;
974392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			in  += 16;
975392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			len -= 16;
976392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    }
977392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    GHASH(ctx,out-j,j);
978392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
979392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
980392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while (len>=16) {
981392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(*block)(ctx->Yi.c,ctx->EKi.c,key);
982392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			++ctr;
983392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (is_endian.little)
984392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				PUTU32(ctx->Yi.c+12,ctr);
985392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
986392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Yi.d[3] = ctr;
987392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			for (i=0; i<16; i+=sizeof(size_t))
988392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				*(size_t *)(ctx->Xi.c+i) ^=
989392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				*(size_t *)(out+i) =
990392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				*(size_t *)(in+i)^*(size_t *)(ctx->EKi.c+i);
991392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			GCM_MUL(ctx,Xi);
992392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			out += 16;
993392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			in  += 16;
994392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			len -= 16;
995392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
996392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
997392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (len) {
998392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(*block)(ctx->Yi.c,ctx->EKi.c,key);
999392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			++ctr;
1000392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (is_endian.little)
1001392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				PUTU32(ctx->Yi.c+12,ctr);
1002392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
1003392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Yi.d[3] = ctr;
1004392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			while (len--) {
1005392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Xi.c[n] ^= out[n] = in[n]^ctx->EKi.c[n];
1006392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				++n;
1007392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1008392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1009392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1010392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->mres = n;
1011392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return 0;
1012392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	} while(0);
1013392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1014392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	for (i=0;i<len;++i) {
1015392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (n==0) {
1016392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(*block)(ctx->Yi.c,ctx->EKi.c,key);
1017392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			++ctr;
1018392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (is_endian.little)
1019392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				PUTU32(ctx->Yi.c+12,ctr);
1020392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
1021392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Yi.d[3] = ctr;
1022392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1023392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->Xi.c[n] ^= out[i] = in[i]^ctx->EKi.c[n];
1024392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		n = (n+1)%16;
1025392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (n==0)
1026392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			GCM_MUL(ctx,Xi);
1027392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1028392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1029392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->mres = n;
1030392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return 0;
1031392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
1032392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1033392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromint CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx,
1034392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		const unsigned char *in, unsigned char *out,
1035392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		size_t len)
1036392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
1037392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	const union { long one; char little; } is_endian = {1};
1038392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	unsigned int n, ctr;
1039392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	size_t i;
1040392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	u64        mlen  = ctx->len.u[1];
1041392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	block128_f block = ctx->block;
1042392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void      *key   = ctx->key;
1043392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef GCM_FUNCREF_4BIT
1044392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*gcm_gmult_p)(u64 Xi[2],const u128 Htable[16])	= ctx->gmult;
1045392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# ifdef GHASH
1046392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*gcm_ghash_p)(u64 Xi[2],const u128 Htable[16],
1047392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				const u8 *inp,size_t len)	= ctx->ghash;
1048392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# endif
1049392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1050392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1051392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	mlen += len;
1052392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (mlen>((U64(1)<<36)-32) || (sizeof(len)==8 && mlen<len))
1053392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return -1;
1054392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->len.u[1] = mlen;
1055392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1056392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (ctx->ares) {
1057392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* First call to decrypt finalizes GHASH(AAD) */
1058392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		GCM_MUL(ctx,Xi);
1059392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->ares = 0;
1060392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1061392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1062392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (is_endian.little)
1063392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr = GETU32(ctx->Yi.c+12);
1064392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else
1065392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr = ctx->Yi.d[3];
1066392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1067392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	n = ctx->mres;
1068392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if !defined(OPENSSL_SMALL_FOOTPRINT)
1069392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (16%sizeof(size_t) == 0) do {	/* always true actually */
1070392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (n) {
1071392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			while (n && len) {
1072392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				u8 c = *(in++);
1073392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				*(out++) = c^ctx->EKi.c[n];
1074392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Xi.c[n] ^= c;
1075392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				--len;
1076392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				n = (n+1)%16;
1077392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1078392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (n==0) GCM_MUL (ctx,Xi);
1079392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else {
1080392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->mres = n;
1081392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				return 0;
1082392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1083392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1084392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(STRICT_ALIGNMENT)
1085392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (((size_t)in|(size_t)out)%sizeof(size_t) != 0)
1086392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			break;
1087392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1088392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(GHASH) && defined(GHASH_CHUNK)
1089392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while (len>=GHASH_CHUNK) {
1090392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    size_t j=GHASH_CHUNK;
1091392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1092392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    GHASH(ctx,in,GHASH_CHUNK);
1093392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    while (j) {
1094392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(*block)(ctx->Yi.c,ctx->EKi.c,key);
1095392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			++ctr;
1096392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (is_endian.little)
1097392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				PUTU32(ctx->Yi.c+12,ctr);
1098392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
1099392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Yi.d[3] = ctr;
1100392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			for (i=0; i<16; i+=sizeof(size_t))
1101392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				*(size_t *)(out+i) =
1102392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				*(size_t *)(in+i)^*(size_t *)(ctx->EKi.c+i);
1103392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			out += 16;
1104392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			in  += 16;
1105392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			j   -= 16;
1106392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    }
1107392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    len -= GHASH_CHUNK;
1108392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1109392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if ((i = (len&(size_t)-16))) {
1110392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    GHASH(ctx,in,i);
1111392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    while (len>=16) {
1112392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(*block)(ctx->Yi.c,ctx->EKi.c,key);
1113392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			++ctr;
1114392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (is_endian.little)
1115392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				PUTU32(ctx->Yi.c+12,ctr);
1116392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
1117392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Yi.d[3] = ctr;
1118392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			for (i=0; i<16; i+=sizeof(size_t))
1119392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				*(size_t *)(out+i) =
1120392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				*(size_t *)(in+i)^*(size_t *)(ctx->EKi.c+i);
1121392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			out += 16;
1122392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			in  += 16;
1123392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			len -= 16;
1124392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    }
1125392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1126392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
1127392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while (len>=16) {
1128392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(*block)(ctx->Yi.c,ctx->EKi.c,key);
1129392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			++ctr;
1130392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (is_endian.little)
1131392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				PUTU32(ctx->Yi.c+12,ctr);
1132392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
1133392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Yi.d[3] = ctr;
1134392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			for (i=0; i<16; i+=sizeof(size_t)) {
1135392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				size_t c = *(size_t *)(in+i);
1136392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				*(size_t *)(out+i) = c^*(size_t *)(ctx->EKi.c+i);
1137392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				*(size_t *)(ctx->Xi.c+i) ^= c;
1138392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1139392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			GCM_MUL(ctx,Xi);
1140392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			out += 16;
1141392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			in  += 16;
1142392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			len -= 16;
1143392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1144392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1145392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (len) {
1146392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(*block)(ctx->Yi.c,ctx->EKi.c,key);
1147392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			++ctr;
1148392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (is_endian.little)
1149392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				PUTU32(ctx->Yi.c+12,ctr);
1150392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
1151392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Yi.d[3] = ctr;
1152392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			while (len--) {
1153392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				u8 c = in[n];
1154392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Xi.c[n] ^= c;
1155392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				out[n] = c^ctx->EKi.c[n];
1156392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				++n;
1157392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1158392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1159392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1160392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->mres = n;
1161392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return 0;
1162392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	} while(0);
1163392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1164392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	for (i=0;i<len;++i) {
1165392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		u8 c;
1166392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (n==0) {
1167392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(*block)(ctx->Yi.c,ctx->EKi.c,key);
1168392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			++ctr;
1169392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (is_endian.little)
1170392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				PUTU32(ctx->Yi.c+12,ctr);
1171392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
1172392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Yi.d[3] = ctr;
1173392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1174392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		c = in[i];
1175392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		out[i] = c^ctx->EKi.c[n];
1176392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->Xi.c[n] ^= c;
1177392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		n = (n+1)%16;
1178392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (n==0)
1179392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			GCM_MUL(ctx,Xi);
1180392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1181392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1182392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->mres = n;
1183392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return 0;
1184392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
1185392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1186392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromint CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx,
1187392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		const unsigned char *in, unsigned char *out,
1188392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		size_t len, ctr128_f stream)
1189392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
1190392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	const union { long one; char little; } is_endian = {1};
1191392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	unsigned int n, ctr;
1192392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	size_t i;
1193392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	u64   mlen = ctx->len.u[1];
1194392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void *key  = ctx->key;
1195392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef GCM_FUNCREF_4BIT
1196392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*gcm_gmult_p)(u64 Xi[2],const u128 Htable[16])	= ctx->gmult;
1197392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# ifdef GHASH
1198392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*gcm_ghash_p)(u64 Xi[2],const u128 Htable[16],
1199392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				const u8 *inp,size_t len)	= ctx->ghash;
1200392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# endif
1201392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1202392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1203392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	mlen += len;
1204392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (mlen>((U64(1)<<36)-32) || (sizeof(len)==8 && mlen<len))
1205392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return -1;
1206392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->len.u[1] = mlen;
1207392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1208392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (ctx->ares) {
1209392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* First call to encrypt finalizes GHASH(AAD) */
1210392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		GCM_MUL(ctx,Xi);
1211392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->ares = 0;
1212392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1213392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1214392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (is_endian.little)
1215392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr = GETU32(ctx->Yi.c+12);
1216392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else
1217392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr = ctx->Yi.d[3];
1218392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1219392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	n = ctx->mres;
1220392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (n) {
1221392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while (n && len) {
1222392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Xi.c[n] ^= *(out++) = *(in++)^ctx->EKi.c[n];
1223392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			--len;
1224392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			n = (n+1)%16;
1225392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1226392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (n==0) GCM_MUL(ctx,Xi);
1227392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else {
1228392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->mres = n;
1229392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			return 0;
1230392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1231392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1232392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT)
1233392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	while (len>=GHASH_CHUNK) {
1234392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		(*stream)(in,out,GHASH_CHUNK/16,key,ctx->Yi.c);
1235392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr += GHASH_CHUNK/16;
1236392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (is_endian.little)
1237392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			PUTU32(ctx->Yi.c+12,ctr);
1238392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
1239392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.d[3] = ctr;
1240392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		GHASH(ctx,out,GHASH_CHUNK);
1241392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		out += GHASH_CHUNK;
1242392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		in  += GHASH_CHUNK;
1243392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		len -= GHASH_CHUNK;
1244392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1245392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1246392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if ((i = (len&(size_t)-16))) {
1247392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		size_t j=i/16;
1248392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1249392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		(*stream)(in,out,j,key,ctx->Yi.c);
1250392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr += (unsigned int)j;
1251392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (is_endian.little)
1252392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			PUTU32(ctx->Yi.c+12,ctr);
1253392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
1254392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.d[3] = ctr;
1255392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		in  += i;
1256392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		len -= i;
1257392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(GHASH)
1258392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		GHASH(ctx,out,i);
1259392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		out += i;
1260392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
1261392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while (j--) {
1262392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			for (i=0;i<16;++i) ctx->Xi.c[i] ^= out[i];
1263392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			GCM_MUL(ctx,Xi);
1264392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			out += 16;
1265392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1266392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1267392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1268392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (len) {
1269392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		(*ctx->block)(ctx->Yi.c,ctx->EKi.c,key);
1270392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		++ctr;
1271392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (is_endian.little)
1272392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			PUTU32(ctx->Yi.c+12,ctr);
1273392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
1274392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.d[3] = ctr;
1275392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while (len--) {
1276392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Xi.c[n] ^= out[n] = in[n]^ctx->EKi.c[n];
1277392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			++n;
1278392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1279392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1280392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1281392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->mres = n;
1282392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return 0;
1283392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
1284392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1285392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromint CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx,
1286392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		const unsigned char *in, unsigned char *out,
1287392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		size_t len,ctr128_f stream)
1288392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
1289392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	const union { long one; char little; } is_endian = {1};
1290392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	unsigned int n, ctr;
1291392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	size_t i;
1292392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	u64   mlen = ctx->len.u[1];
1293392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void *key  = ctx->key;
1294392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef GCM_FUNCREF_4BIT
1295392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*gcm_gmult_p)(u64 Xi[2],const u128 Htable[16])	= ctx->gmult;
1296392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# ifdef GHASH
1297392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*gcm_ghash_p)(u64 Xi[2],const u128 Htable[16],
1298392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				const u8 *inp,size_t len)	= ctx->ghash;
1299392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# endif
1300392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1301392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1302392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	mlen += len;
1303392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (mlen>((U64(1)<<36)-32) || (sizeof(len)==8 && mlen<len))
1304392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return -1;
1305392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->len.u[1] = mlen;
1306392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1307392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (ctx->ares) {
1308392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* First call to decrypt finalizes GHASH(AAD) */
1309392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		GCM_MUL(ctx,Xi);
1310392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->ares = 0;
1311392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1312392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1313392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (is_endian.little)
1314392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr = GETU32(ctx->Yi.c+12);
1315392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else
1316392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr = ctx->Yi.d[3];
1317392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1318392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	n = ctx->mres;
1319392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (n) {
1320392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while (n && len) {
1321392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			u8 c = *(in++);
1322392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			*(out++) = c^ctx->EKi.c[n];
1323392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Xi.c[n] ^= c;
1324392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			--len;
1325392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			n = (n+1)%16;
1326392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1327392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (n==0) GCM_MUL (ctx,Xi);
1328392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else {
1329392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->mres = n;
1330392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			return 0;
1331392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1332392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1333392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT)
1334392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	while (len>=GHASH_CHUNK) {
1335392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		GHASH(ctx,in,GHASH_CHUNK);
1336392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		(*stream)(in,out,GHASH_CHUNK/16,key,ctx->Yi.c);
1337392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr += GHASH_CHUNK/16;
1338392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (is_endian.little)
1339392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			PUTU32(ctx->Yi.c+12,ctr);
1340392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
1341392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.d[3] = ctr;
1342392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		out += GHASH_CHUNK;
1343392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		in  += GHASH_CHUNK;
1344392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		len -= GHASH_CHUNK;
1345392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1346392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1347392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if ((i = (len&(size_t)-16))) {
1348392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		size_t j=i/16;
1349392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1350392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(GHASH)
1351392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		GHASH(ctx,in,i);
1352392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
1353392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while (j--) {
1354392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			size_t k;
1355392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			for (k=0;k<16;++k) ctx->Xi.c[k] ^= in[k];
1356392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			GCM_MUL(ctx,Xi);
1357392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			in += 16;
1358392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1359392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		j   = i/16;
1360392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		in -= i;
1361392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1362392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		(*stream)(in,out,j,key,ctx->Yi.c);
1363392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr += (unsigned int)j;
1364392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (is_endian.little)
1365392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			PUTU32(ctx->Yi.c+12,ctr);
1366392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
1367392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.d[3] = ctr;
1368392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		out += i;
1369392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		in  += i;
1370392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		len -= i;
1371392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1372392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (len) {
1373392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		(*ctx->block)(ctx->Yi.c,ctx->EKi.c,key);
1374392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		++ctr;
1375392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (is_endian.little)
1376392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			PUTU32(ctx->Yi.c+12,ctr);
1377392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
1378392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.d[3] = ctr;
1379392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while (len--) {
1380392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			u8 c = in[n];
1381392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Xi.c[n] ^= c;
1382392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			out[n] = c^ctx->EKi.c[n];
1383392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			++n;
1384392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1385392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1386392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1387392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->mres = n;
1388392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return 0;
1389392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
1390392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1391392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromint CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx,const unsigned char *tag,
1392392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			size_t len)
1393392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
1394392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	const union { long one; char little; } is_endian = {1};
1395392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	u64 alen = ctx->len.u[0]<<3;
1396392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	u64 clen = ctx->len.u[1]<<3;
1397392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef GCM_FUNCREF_4BIT
1398392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*gcm_gmult_p)(u64 Xi[2],const u128 Htable[16])	= ctx->gmult;
1399392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1400392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
140104ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom	if (ctx->mres || ctx->ares)
1402392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		GCM_MUL(ctx,Xi);
1403392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1404392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (is_endian.little) {
1405392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef BSWAP8
1406392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		alen = BSWAP8(alen);
1407392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		clen = BSWAP8(clen);
1408392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
1409392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		u8 *p = ctx->len.c;
1410392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1411392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->len.u[0] = alen;
1412392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->len.u[1] = clen;
1413392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1414392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		alen = (u64)GETU32(p)  <<32|GETU32(p+4);
1415392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		clen = (u64)GETU32(p+8)<<32|GETU32(p+12);
1416392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1417392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1418392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1419392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->Xi.u[0] ^= alen;
1420392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->Xi.u[1] ^= clen;
1421392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	GCM_MUL(ctx,Xi);
1422392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1423392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->Xi.u[0] ^= ctx->EK0.u[0];
1424392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->Xi.u[1] ^= ctx->EK0.u[1];
1425392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1426392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (tag && len<=sizeof(ctx->Xi))
1427392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return memcmp(ctx->Xi.c,tag,len);
1428392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else
1429392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return -1;
1430392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
1431392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1432392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromvoid CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, unsigned char *tag, size_t len)
1433392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
1434392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	CRYPTO_gcm128_finish(ctx, NULL, 0);
1435392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	memcpy(tag, ctx->Xi.c, len<=sizeof(ctx->Xi.c)?len:sizeof(ctx->Xi.c));
1436392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
1437392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1438392aa7cc7d2b122614c5393c3e357da07fd07af3Brian CarlstromGCM128_CONTEXT *CRYPTO_gcm128_new(void *key, block128_f block)
1439392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
1440392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	GCM128_CONTEXT *ret;
1441392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1442392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if ((ret = (GCM128_CONTEXT *)OPENSSL_malloc(sizeof(GCM128_CONTEXT))))
1443392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		CRYPTO_gcm128_init(ret,key,block);
1444392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1445392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return ret;
1446392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
1447392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1448392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromvoid CRYPTO_gcm128_release(GCM128_CONTEXT *ctx)
1449392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
1450392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (ctx) {
1451392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		OPENSSL_cleanse(ctx,sizeof(*ctx));
1452392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		OPENSSL_free(ctx);
1453392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1454392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
1455392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1456392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(SELFTEST)
1457392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#include <stdio.h>
1458392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#include <openssl/aes.h>
1459392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1460392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 1 */
1461392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	K1[16],
1462392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		*P1=NULL,
1463392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		*A1=NULL,
1464392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		IV1[12],
1465392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		*C1=NULL,
1466392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T1[]=  {0x58,0xe2,0xfc,0xce,0xfa,0x7e,0x30,0x61,0x36,0x7f,0x1d,0x57,0xa4,0xe7,0x45,0x5a};
1467392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1468392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 2 */
1469392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define K2 K1
1470392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define A2 A1
1471392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define IV2 IV1
1472392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	P2[16],
1473392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C2[]=  {0x03,0x88,0xda,0xce,0x60,0xb6,0xa3,0x92,0xf3,0x28,0xc2,0xb9,0x71,0xb2,0xfe,0x78},
1474392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T2[]=  {0xab,0x6e,0x47,0xd4,0x2c,0xec,0x13,0xbd,0xf5,0x3a,0x67,0xb2,0x12,0x57,0xbd,0xdf};
1475392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1476392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 3 */
1477392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define A3 A2
1478392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	K3[]=  {0xfe,0xff,0xe9,0x92,0x86,0x65,0x73,0x1c,0x6d,0x6a,0x8f,0x94,0x67,0x30,0x83,0x08},
1479392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		P3[]=  {0xd9,0x31,0x32,0x25,0xf8,0x84,0x06,0xe5,0xa5,0x59,0x09,0xc5,0xaf,0xf5,0x26,0x9a,
1480392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x86,0xa7,0xa9,0x53,0x15,0x34,0xf7,0xda,0x2e,0x4c,0x30,0x3d,0x8a,0x31,0x8a,0x72,
1481392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x1c,0x3c,0x0c,0x95,0x95,0x68,0x09,0x53,0x2f,0xcf,0x0e,0x24,0x49,0xa6,0xb5,0x25,
1482392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xb1,0x6a,0xed,0xf5,0xaa,0x0d,0xe6,0x57,0xba,0x63,0x7b,0x39,0x1a,0xaf,0xd2,0x55},
1483392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		IV3[]= {0xca,0xfe,0xba,0xbe,0xfa,0xce,0xdb,0xad,0xde,0xca,0xf8,0x88},
1484392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C3[]=  {0x42,0x83,0x1e,0xc2,0x21,0x77,0x74,0x24,0x4b,0x72,0x21,0xb7,0x84,0xd0,0xd4,0x9c,
1485392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xe3,0xaa,0x21,0x2f,0x2c,0x02,0xa4,0xe0,0x35,0xc1,0x7e,0x23,0x29,0xac,0xa1,0x2e,
1486392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x21,0xd5,0x14,0xb2,0x54,0x66,0x93,0x1c,0x7d,0x8f,0x6a,0x5a,0xac,0x84,0xaa,0x05,
1487392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x1b,0xa3,0x0b,0x39,0x6a,0x0a,0xac,0x97,0x3d,0x58,0xe0,0x91,0x47,0x3f,0x59,0x85},
1488392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T3[]=  {0x4d,0x5c,0x2a,0xf3,0x27,0xcd,0x64,0xa6,0x2c,0xf3,0x5a,0xbd,0x2b,0xa6,0xfa,0xb4};
1489392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1490392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 4 */
1491392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define K4 K3
1492392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define IV4 IV3
1493392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	P4[]=  {0xd9,0x31,0x32,0x25,0xf8,0x84,0x06,0xe5,0xa5,0x59,0x09,0xc5,0xaf,0xf5,0x26,0x9a,
1494392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x86,0xa7,0xa9,0x53,0x15,0x34,0xf7,0xda,0x2e,0x4c,0x30,0x3d,0x8a,0x31,0x8a,0x72,
1495392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x1c,0x3c,0x0c,0x95,0x95,0x68,0x09,0x53,0x2f,0xcf,0x0e,0x24,0x49,0xa6,0xb5,0x25,
1496392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xb1,0x6a,0xed,0xf5,0xaa,0x0d,0xe6,0x57,0xba,0x63,0x7b,0x39},
1497392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		A4[]=  {0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef,0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef,
1498392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xab,0xad,0xda,0xd2},
1499392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C4[]=  {0x42,0x83,0x1e,0xc2,0x21,0x77,0x74,0x24,0x4b,0x72,0x21,0xb7,0x84,0xd0,0xd4,0x9c,
1500392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xe3,0xaa,0x21,0x2f,0x2c,0x02,0xa4,0xe0,0x35,0xc1,0x7e,0x23,0x29,0xac,0xa1,0x2e,
1501392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x21,0xd5,0x14,0xb2,0x54,0x66,0x93,0x1c,0x7d,0x8f,0x6a,0x5a,0xac,0x84,0xaa,0x05,
1502392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x1b,0xa3,0x0b,0x39,0x6a,0x0a,0xac,0x97,0x3d,0x58,0xe0,0x91},
1503392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T4[]=  {0x5b,0xc9,0x4f,0xbc,0x32,0x21,0xa5,0xdb,0x94,0xfa,0xe9,0x5a,0xe7,0x12,0x1a,0x47};
1504392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1505392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 5 */
1506392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define K5 K4
1507392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define P5 P4
1508392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define A5 A4
1509392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	IV5[]= {0xca,0xfe,0xba,0xbe,0xfa,0xce,0xdb,0xad},
1510392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C5[]=  {0x61,0x35,0x3b,0x4c,0x28,0x06,0x93,0x4a,0x77,0x7f,0xf5,0x1f,0xa2,0x2a,0x47,0x55,
1511392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x69,0x9b,0x2a,0x71,0x4f,0xcd,0xc6,0xf8,0x37,0x66,0xe5,0xf9,0x7b,0x6c,0x74,0x23,
1512392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x73,0x80,0x69,0x00,0xe4,0x9f,0x24,0xb2,0x2b,0x09,0x75,0x44,0xd4,0x89,0x6b,0x42,
1513392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x49,0x89,0xb5,0xe1,0xeb,0xac,0x0f,0x07,0xc2,0x3f,0x45,0x98},
1514392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T5[]=  {0x36,0x12,0xd2,0xe7,0x9e,0x3b,0x07,0x85,0x56,0x1b,0xe1,0x4a,0xac,0xa2,0xfc,0xcb};
1515392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1516392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 6 */
1517392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define K6 K5
1518392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define P6 P5
1519392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define A6 A5
1520392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	IV6[]= {0x93,0x13,0x22,0x5d,0xf8,0x84,0x06,0xe5,0x55,0x90,0x9c,0x5a,0xff,0x52,0x69,0xaa,
1521392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x6a,0x7a,0x95,0x38,0x53,0x4f,0x7d,0xa1,0xe4,0xc3,0x03,0xd2,0xa3,0x18,0xa7,0x28,
1522392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xc3,0xc0,0xc9,0x51,0x56,0x80,0x95,0x39,0xfc,0xf0,0xe2,0x42,0x9a,0x6b,0x52,0x54,
1523392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x16,0xae,0xdb,0xf5,0xa0,0xde,0x6a,0x57,0xa6,0x37,0xb3,0x9b},
1524392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C6[]=  {0x8c,0xe2,0x49,0x98,0x62,0x56,0x15,0xb6,0x03,0xa0,0x33,0xac,0xa1,0x3f,0xb8,0x94,
1525392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xbe,0x91,0x12,0xa5,0xc3,0xa2,0x11,0xa8,0xba,0x26,0x2a,0x3c,0xca,0x7e,0x2c,0xa7,
1526392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x01,0xe4,0xa9,0xa4,0xfb,0xa4,0x3c,0x90,0xcc,0xdc,0xb2,0x81,0xd4,0x8c,0x7c,0x6f,
1527392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xd6,0x28,0x75,0xd2,0xac,0xa4,0x17,0x03,0x4c,0x34,0xae,0xe5},
1528392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T6[]=  {0x61,0x9c,0xc5,0xae,0xff,0xfe,0x0b,0xfa,0x46,0x2a,0xf4,0x3c,0x16,0x99,0xd0,0x50};
1529392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1530392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 7 */
1531392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8 K7[24],
1532392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		*P7=NULL,
1533392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		*A7=NULL,
1534392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		IV7[12],
1535392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		*C7=NULL,
1536392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T7[]=  {0xcd,0x33,0xb2,0x8a,0xc7,0x73,0xf7,0x4b,0xa0,0x0e,0xd1,0xf3,0x12,0x57,0x24,0x35};
1537392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1538392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 8 */
1539392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define K8 K7
1540392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define IV8 IV7
1541392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define A8 A7
1542392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	P8[16],
1543392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C8[]=  {0x98,0xe7,0x24,0x7c,0x07,0xf0,0xfe,0x41,0x1c,0x26,0x7e,0x43,0x84,0xb0,0xf6,0x00},
1544392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T8[]=  {0x2f,0xf5,0x8d,0x80,0x03,0x39,0x27,0xab,0x8e,0xf4,0xd4,0x58,0x75,0x14,0xf0,0xfb};
1545392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1546392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 9 */
1547392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define A9 A8
1548392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	K9[]=  {0xfe,0xff,0xe9,0x92,0x86,0x65,0x73,0x1c,0x6d,0x6a,0x8f,0x94,0x67,0x30,0x83,0x08,
1549392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xfe,0xff,0xe9,0x92,0x86,0x65,0x73,0x1c},
1550392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		P9[]=  {0xd9,0x31,0x32,0x25,0xf8,0x84,0x06,0xe5,0xa5,0x59,0x09,0xc5,0xaf,0xf5,0x26,0x9a,
1551392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x86,0xa7,0xa9,0x53,0x15,0x34,0xf7,0xda,0x2e,0x4c,0x30,0x3d,0x8a,0x31,0x8a,0x72,
1552392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x1c,0x3c,0x0c,0x95,0x95,0x68,0x09,0x53,0x2f,0xcf,0x0e,0x24,0x49,0xa6,0xb5,0x25,
1553392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xb1,0x6a,0xed,0xf5,0xaa,0x0d,0xe6,0x57,0xba,0x63,0x7b,0x39,0x1a,0xaf,0xd2,0x55},
1554392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		IV9[]= {0xca,0xfe,0xba,0xbe,0xfa,0xce,0xdb,0xad,0xde,0xca,0xf8,0x88},
1555392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C9[]=  {0x39,0x80,0xca,0x0b,0x3c,0x00,0xe8,0x41,0xeb,0x06,0xfa,0xc4,0x87,0x2a,0x27,0x57,
1556392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x85,0x9e,0x1c,0xea,0xa6,0xef,0xd9,0x84,0x62,0x85,0x93,0xb4,0x0c,0xa1,0xe1,0x9c,
1557392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x7d,0x77,0x3d,0x00,0xc1,0x44,0xc5,0x25,0xac,0x61,0x9d,0x18,0xc8,0x4a,0x3f,0x47,
1558392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x18,0xe2,0x44,0x8b,0x2f,0xe3,0x24,0xd9,0xcc,0xda,0x27,0x10,0xac,0xad,0xe2,0x56},
1559392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T9[]=  {0x99,0x24,0xa7,0xc8,0x58,0x73,0x36,0xbf,0xb1,0x18,0x02,0x4d,0xb8,0x67,0x4a,0x14};
1560392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1561392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 10 */
1562392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define K10 K9
1563392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define IV10 IV9
1564392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	P10[]= {0xd9,0x31,0x32,0x25,0xf8,0x84,0x06,0xe5,0xa5,0x59,0x09,0xc5,0xaf,0xf5,0x26,0x9a,
1565392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x86,0xa7,0xa9,0x53,0x15,0x34,0xf7,0xda,0x2e,0x4c,0x30,0x3d,0x8a,0x31,0x8a,0x72,
1566392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x1c,0x3c,0x0c,0x95,0x95,0x68,0x09,0x53,0x2f,0xcf,0x0e,0x24,0x49,0xa6,0xb5,0x25,
1567392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xb1,0x6a,0xed,0xf5,0xaa,0x0d,0xe6,0x57,0xba,0x63,0x7b,0x39},
1568392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		A10[]= {0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef,0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef,
1569392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xab,0xad,0xda,0xd2},
1570392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C10[]= {0x39,0x80,0xca,0x0b,0x3c,0x00,0xe8,0x41,0xeb,0x06,0xfa,0xc4,0x87,0x2a,0x27,0x57,
1571392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x85,0x9e,0x1c,0xea,0xa6,0xef,0xd9,0x84,0x62,0x85,0x93,0xb4,0x0c,0xa1,0xe1,0x9c,
1572392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x7d,0x77,0x3d,0x00,0xc1,0x44,0xc5,0x25,0xac,0x61,0x9d,0x18,0xc8,0x4a,0x3f,0x47,
1573392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x18,0xe2,0x44,0x8b,0x2f,0xe3,0x24,0xd9,0xcc,0xda,0x27,0x10},
1574392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T10[]= {0x25,0x19,0x49,0x8e,0x80,0xf1,0x47,0x8f,0x37,0xba,0x55,0xbd,0x6d,0x27,0x61,0x8c};
1575392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1576392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 11 */
1577392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define K11 K10
1578392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define P11 P10
1579392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define A11 A10
1580392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	IV11[]={0xca,0xfe,0xba,0xbe,0xfa,0xce,0xdb,0xad},
1581392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C11[]= {0x0f,0x10,0xf5,0x99,0xae,0x14,0xa1,0x54,0xed,0x24,0xb3,0x6e,0x25,0x32,0x4d,0xb8,
1582392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xc5,0x66,0x63,0x2e,0xf2,0xbb,0xb3,0x4f,0x83,0x47,0x28,0x0f,0xc4,0x50,0x70,0x57,
1583392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xfd,0xdc,0x29,0xdf,0x9a,0x47,0x1f,0x75,0xc6,0x65,0x41,0xd4,0xd4,0xda,0xd1,0xc9,
1584392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xe9,0x3a,0x19,0xa5,0x8e,0x8b,0x47,0x3f,0xa0,0xf0,0x62,0xf7},
1585392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T11[]= {0x65,0xdc,0xc5,0x7f,0xcf,0x62,0x3a,0x24,0x09,0x4f,0xcc,0xa4,0x0d,0x35,0x33,0xf8};
1586392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1587392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 12 */
1588392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define K12 K11
1589392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define P12 P11
1590392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define A12 A11
1591392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	IV12[]={0x93,0x13,0x22,0x5d,0xf8,0x84,0x06,0xe5,0x55,0x90,0x9c,0x5a,0xff,0x52,0x69,0xaa,
1592392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x6a,0x7a,0x95,0x38,0x53,0x4f,0x7d,0xa1,0xe4,0xc3,0x03,0xd2,0xa3,0x18,0xa7,0x28,
1593392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xc3,0xc0,0xc9,0x51,0x56,0x80,0x95,0x39,0xfc,0xf0,0xe2,0x42,0x9a,0x6b,0x52,0x54,
1594392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x16,0xae,0xdb,0xf5,0xa0,0xde,0x6a,0x57,0xa6,0x37,0xb3,0x9b},
1595392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C12[]= {0xd2,0x7e,0x88,0x68,0x1c,0xe3,0x24,0x3c,0x48,0x30,0x16,0x5a,0x8f,0xdc,0xf9,0xff,
1596392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x1d,0xe9,0xa1,0xd8,0xe6,0xb4,0x47,0xef,0x6e,0xf7,0xb7,0x98,0x28,0x66,0x6e,0x45,
1597392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x81,0xe7,0x90,0x12,0xaf,0x34,0xdd,0xd9,0xe2,0xf0,0x37,0x58,0x9b,0x29,0x2d,0xb3,
1598392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xe6,0x7c,0x03,0x67,0x45,0xfa,0x22,0xe7,0xe9,0xb7,0x37,0x3b},
1599392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T12[]= {0xdc,0xf5,0x66,0xff,0x29,0x1c,0x25,0xbb,0xb8,0x56,0x8f,0xc3,0xd3,0x76,0xa6,0xd9};
1600392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1601392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 13 */
1602392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	K13[32],
1603392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		*P13=NULL,
1604392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		*A13=NULL,
1605392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		IV13[12],
1606392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		*C13=NULL,
1607392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T13[]={0x53,0x0f,0x8a,0xfb,0xc7,0x45,0x36,0xb9,0xa9,0x63,0xb4,0xf1,0xc4,0xcb,0x73,0x8b};
1608392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1609392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 14 */
1610392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define K14 K13
1611392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define A14 A13
1612392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	P14[16],
1613392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		IV14[12],
1614392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C14[]= {0xce,0xa7,0x40,0x3d,0x4d,0x60,0x6b,0x6e,0x07,0x4e,0xc5,0xd3,0xba,0xf3,0x9d,0x18},
1615392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T14[]= {0xd0,0xd1,0xc8,0xa7,0x99,0x99,0x6b,0xf0,0x26,0x5b,0x98,0xb5,0xd4,0x8a,0xb9,0x19};
1616392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1617392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 15 */
1618392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define A15 A14
1619392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	K15[]= {0xfe,0xff,0xe9,0x92,0x86,0x65,0x73,0x1c,0x6d,0x6a,0x8f,0x94,0x67,0x30,0x83,0x08,
1620392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xfe,0xff,0xe9,0x92,0x86,0x65,0x73,0x1c,0x6d,0x6a,0x8f,0x94,0x67,0x30,0x83,0x08},
1621392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		P15[]= {0xd9,0x31,0x32,0x25,0xf8,0x84,0x06,0xe5,0xa5,0x59,0x09,0xc5,0xaf,0xf5,0x26,0x9a,
1622392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x86,0xa7,0xa9,0x53,0x15,0x34,0xf7,0xda,0x2e,0x4c,0x30,0x3d,0x8a,0x31,0x8a,0x72,
1623392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x1c,0x3c,0x0c,0x95,0x95,0x68,0x09,0x53,0x2f,0xcf,0x0e,0x24,0x49,0xa6,0xb5,0x25,
1624392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xb1,0x6a,0xed,0xf5,0xaa,0x0d,0xe6,0x57,0xba,0x63,0x7b,0x39,0x1a,0xaf,0xd2,0x55},
1625392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		IV15[]={0xca,0xfe,0xba,0xbe,0xfa,0xce,0xdb,0xad,0xde,0xca,0xf8,0x88},
1626392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C15[]= {0x52,0x2d,0xc1,0xf0,0x99,0x56,0x7d,0x07,0xf4,0x7f,0x37,0xa3,0x2a,0x84,0x42,0x7d,
1627392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x64,0x3a,0x8c,0xdc,0xbf,0xe5,0xc0,0xc9,0x75,0x98,0xa2,0xbd,0x25,0x55,0xd1,0xaa,
1628392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x8c,0xb0,0x8e,0x48,0x59,0x0d,0xbb,0x3d,0xa7,0xb0,0x8b,0x10,0x56,0x82,0x88,0x38,
1629392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xc5,0xf6,0x1e,0x63,0x93,0xba,0x7a,0x0a,0xbc,0xc9,0xf6,0x62,0x89,0x80,0x15,0xad},
1630392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T15[]= {0xb0,0x94,0xda,0xc5,0xd9,0x34,0x71,0xbd,0xec,0x1a,0x50,0x22,0x70,0xe3,0xcc,0x6c};
1631392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1632392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 16 */
1633392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define K16 K15
1634392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define IV16 IV15
1635392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	P16[]= {0xd9,0x31,0x32,0x25,0xf8,0x84,0x06,0xe5,0xa5,0x59,0x09,0xc5,0xaf,0xf5,0x26,0x9a,
1636392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x86,0xa7,0xa9,0x53,0x15,0x34,0xf7,0xda,0x2e,0x4c,0x30,0x3d,0x8a,0x31,0x8a,0x72,
1637392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x1c,0x3c,0x0c,0x95,0x95,0x68,0x09,0x53,0x2f,0xcf,0x0e,0x24,0x49,0xa6,0xb5,0x25,
1638392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xb1,0x6a,0xed,0xf5,0xaa,0x0d,0xe6,0x57,0xba,0x63,0x7b,0x39},
1639392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		A16[]= {0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef,0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef,
1640392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xab,0xad,0xda,0xd2},
1641392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C16[]= {0x52,0x2d,0xc1,0xf0,0x99,0x56,0x7d,0x07,0xf4,0x7f,0x37,0xa3,0x2a,0x84,0x42,0x7d,
1642392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x64,0x3a,0x8c,0xdc,0xbf,0xe5,0xc0,0xc9,0x75,0x98,0xa2,0xbd,0x25,0x55,0xd1,0xaa,
1643392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x8c,0xb0,0x8e,0x48,0x59,0x0d,0xbb,0x3d,0xa7,0xb0,0x8b,0x10,0x56,0x82,0x88,0x38,
1644392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xc5,0xf6,0x1e,0x63,0x93,0xba,0x7a,0x0a,0xbc,0xc9,0xf6,0x62},
1645392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T16[]= {0x76,0xfc,0x6e,0xce,0x0f,0x4e,0x17,0x68,0xcd,0xdf,0x88,0x53,0xbb,0x2d,0x55,0x1b};
1646392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1647392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 17 */
1648392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define K17 K16
1649392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define P17 P16
1650392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define A17 A16
1651392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	IV17[]={0xca,0xfe,0xba,0xbe,0xfa,0xce,0xdb,0xad},
1652392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C17[]= {0xc3,0x76,0x2d,0xf1,0xca,0x78,0x7d,0x32,0xae,0x47,0xc1,0x3b,0xf1,0x98,0x44,0xcb,
1653392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xaf,0x1a,0xe1,0x4d,0x0b,0x97,0x6a,0xfa,0xc5,0x2f,0xf7,0xd7,0x9b,0xba,0x9d,0xe0,
1654392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xfe,0xb5,0x82,0xd3,0x39,0x34,0xa4,0xf0,0x95,0x4c,0xc2,0x36,0x3b,0xc7,0x3f,0x78,
1655392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x62,0xac,0x43,0x0e,0x64,0xab,0xe4,0x99,0xf4,0x7c,0x9b,0x1f},
1656392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T17[]= {0x3a,0x33,0x7d,0xbf,0x46,0xa7,0x92,0xc4,0x5e,0x45,0x49,0x13,0xfe,0x2e,0xa8,0xf2};
1657392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1658392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 18 */
1659392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define K18 K17
1660392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define P18 P17
1661392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define A18 A17
1662392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	IV18[]={0x93,0x13,0x22,0x5d,0xf8,0x84,0x06,0xe5,0x55,0x90,0x9c,0x5a,0xff,0x52,0x69,0xaa,
1663392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x6a,0x7a,0x95,0x38,0x53,0x4f,0x7d,0xa1,0xe4,0xc3,0x03,0xd2,0xa3,0x18,0xa7,0x28,
1664392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xc3,0xc0,0xc9,0x51,0x56,0x80,0x95,0x39,0xfc,0xf0,0xe2,0x42,0x9a,0x6b,0x52,0x54,
1665392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x16,0xae,0xdb,0xf5,0xa0,0xde,0x6a,0x57,0xa6,0x37,0xb3,0x9b},
1666392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C18[]= {0x5a,0x8d,0xef,0x2f,0x0c,0x9e,0x53,0xf1,0xf7,0x5d,0x78,0x53,0x65,0x9e,0x2a,0x20,
1667392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xee,0xb2,0xb2,0x2a,0xaf,0xde,0x64,0x19,0xa0,0x58,0xab,0x4f,0x6f,0x74,0x6b,0xf4,
1668392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x0f,0xc0,0xc3,0xb7,0x80,0xf2,0x44,0x45,0x2d,0xa3,0xeb,0xf1,0xc5,0xd8,0x2c,0xde,
1669392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xa2,0x41,0x89,0x97,0x20,0x0e,0xf8,0x2e,0x44,0xae,0x7e,0x3f},
1670392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T18[]= {0xa4,0x4a,0x82,0x66,0xee,0x1c,0x8e,0xb0,0xc8,0xb5,0xd4,0xcf,0x5a,0xe9,0xf1,0x9a};
1671392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1672392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define TEST_CASE(n)	do {					\
1673392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	u8 out[sizeof(P##n)];					\
1674392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	AES_set_encrypt_key(K##n,sizeof(K##n)*8,&key);		\
1675392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	CRYPTO_gcm128_init(&ctx,&key,(block128_f)AES_encrypt);	\
1676392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	CRYPTO_gcm128_setiv(&ctx,IV##n,sizeof(IV##n));		\
1677392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	memset(out,0,sizeof(out));				\
1678392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (A##n) CRYPTO_gcm128_aad(&ctx,A##n,sizeof(A##n));	\
1679392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (P##n) CRYPTO_gcm128_encrypt(&ctx,P##n,out,sizeof(out));	\
1680392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (CRYPTO_gcm128_finish(&ctx,T##n,16) ||		\
1681392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	    (C##n && memcmp(out,C##n,sizeof(out))))		\
1682392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret++, printf ("encrypt test#%d failed.\n",n);	\
1683392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	CRYPTO_gcm128_setiv(&ctx,IV##n,sizeof(IV##n));		\
1684392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	memset(out,0,sizeof(out));				\
1685392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (A##n) CRYPTO_gcm128_aad(&ctx,A##n,sizeof(A##n));	\
1686392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (C##n) CRYPTO_gcm128_decrypt(&ctx,C##n,out,sizeof(out));	\
1687392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (CRYPTO_gcm128_finish(&ctx,T##n,16) ||		\
1688392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	    (P##n && memcmp(out,P##n,sizeof(out))))		\
1689392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret++, printf ("decrypt test#%d failed.\n",n);	\
1690392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	} while(0)
1691392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1692392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromint main()
1693392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
1694392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	GCM128_CONTEXT ctx;
1695392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	AES_KEY key;
1696392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int ret=0;
1697392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1698392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(1);
1699392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(2);
1700392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(3);
1701392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(4);
1702392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(5);
1703392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(6);
1704392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(7);
1705392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(8);
1706392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(9);
1707392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(10);
1708392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(11);
1709392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(12);
1710392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(13);
1711392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(14);
1712392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(15);
1713392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(16);
1714392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(17);
1715392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(18);
1716392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1717392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef OPENSSL_CPUID_OBJ
1718392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
1719392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	size_t start,stop,gcm_t,ctr_t,OPENSSL_rdtsc();
1720392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	union { u64 u; u8 c[1024]; } buf;
1721392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int i;
1722392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1723392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	AES_set_encrypt_key(K1,sizeof(K1)*8,&key);
1724392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	CRYPTO_gcm128_init(&ctx,&key,(block128_f)AES_encrypt);
1725392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	CRYPTO_gcm128_setiv(&ctx,IV1,sizeof(IV1));
1726392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1727392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	CRYPTO_gcm128_encrypt(&ctx,buf.c,buf.c,sizeof(buf));
1728392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	start = OPENSSL_rdtsc();
1729392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	CRYPTO_gcm128_encrypt(&ctx,buf.c,buf.c,sizeof(buf));
1730392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	gcm_t = OPENSSL_rdtsc() - start;
1731392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1732392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	CRYPTO_ctr128_encrypt(buf.c,buf.c,sizeof(buf),
1733392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			&key,ctx.Yi.c,ctx.EKi.c,&ctx.mres,
1734392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(block128_f)AES_encrypt);
1735392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	start = OPENSSL_rdtsc();
1736392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	CRYPTO_ctr128_encrypt(buf.c,buf.c,sizeof(buf),
1737392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			&key,ctx.Yi.c,ctx.EKi.c,&ctx.mres,
1738392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(block128_f)AES_encrypt);
1739392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctr_t = OPENSSL_rdtsc() - start;
1740392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1741392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	printf("%.2f-%.2f=%.2f\n",
1742392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			gcm_t/(double)sizeof(buf),
1743392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctr_t/(double)sizeof(buf),
1744392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(gcm_t-ctr_t)/(double)sizeof(buf));
1745392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef GHASH
1746392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	GHASH(&ctx,buf.c,sizeof(buf));
1747392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	start = OPENSSL_rdtsc();
1748392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	for (i=0;i<100;++i) GHASH(&ctx,buf.c,sizeof(buf));
1749392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	gcm_t = OPENSSL_rdtsc() - start;
1750392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	printf("%.2f\n",gcm_t/(double)sizeof(buf)/(double)i);
1751392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1752392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1753392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1754392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1755392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return ret;
1756392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
1757392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1758