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
6453f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root#if	TABLE_BITS==4 && (defined(GHASH_ASM) || defined(OPENSSL_CPUID_OBJ))
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
6663f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root# elif defined(__arm__) || defined(__arm) || defined(__aarch64__)
667392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#  include "arm_arch.h"
668392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#  if __ARM_ARCH__>=7
669392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#   define GHASH_ASM_ARM
670392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#   define GCM_FUNCREF_4BIT
6713f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root#   define PMULL_CAPABLE	(OPENSSL_armcap_P & ARMV8_PMULL)
6723f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root#   if defined(__arm__) || defined(__arm)
6733f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root#    define NEON_CAPABLE	(OPENSSL_armcap_P & ARMV7_NEON)
6743f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root#   endif
6753f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Rootvoid gcm_init_neon(u128 Htable[16],const u64 Xi[2]);
676392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromvoid gcm_gmult_neon(u64 Xi[2],const u128 Htable[16]);
677392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromvoid gcm_ghash_neon(u64 Xi[2],const u128 Htable[16],const u8 *inp,size_t len);
6783f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Rootvoid gcm_init_v8(u128 Htable[16],const u64 Xi[2]);
6793f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Rootvoid gcm_gmult_v8(u64 Xi[2],const u128 Htable[16]);
6803f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Rootvoid gcm_ghash_v8(u64 Xi[2],const u128 Htable[16],const u8 *inp,size_t len);
681392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#  endif
682392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# endif
683392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
684392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
685392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef GCM_FUNCREF_4BIT
686392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# undef  GCM_MUL
687392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# define GCM_MUL(ctx,Xi)	(*gcm_gmult_p)(ctx->Xi.u,ctx->Htable)
688392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# ifdef GHASH
689392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#  undef  GHASH
690392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#  define GHASH(ctx,in,len)	(*gcm_ghash_p)(ctx->Xi.u,ctx->Htable,in,len)
691392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# endif
692392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
693392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
694392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromvoid CRYPTO_gcm128_init(GCM128_CONTEXT *ctx,void *key,block128_f block)
695392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
696392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	const union { long one; char little; } is_endian = {1};
697392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
698392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	memset(ctx,0,sizeof(*ctx));
699392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->block = block;
700392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->key   = key;
701392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
702392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	(*block)(ctx->H.c,ctx->H.c,key);
703392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
704392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (is_endian.little) {
705392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* H is stored in host byte order */
706392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef BSWAP8
707392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->H.u[0] = BSWAP8(ctx->H.u[0]);
708392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->H.u[1] = BSWAP8(ctx->H.u[1]);
709392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
710392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		u8 *p = ctx->H.c;
711392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		u64 hi,lo;
712392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		hi = (u64)GETU32(p)  <<32|GETU32(p+4);
713392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		lo = (u64)GETU32(p+8)<<32|GETU32(p+12);
714392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->H.u[0] = hi;
715392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->H.u[1] = lo;
716392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
717392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
718392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
719392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if	TABLE_BITS==8
720392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	gcm_init_8bit(ctx->Htable,ctx->H.u);
721392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#elif	TABLE_BITS==4
722392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# if	defined(GHASH_ASM_X86_OR_64)
723392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#  if	!defined(GHASH_ASM_X86) || defined(OPENSSL_IA32_SSE2)
724392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (OPENSSL_ia32cap_P[0]&(1<<24) &&	/* check FXSR bit */
725392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	    OPENSSL_ia32cap_P[1]&(1<<1) ) {	/* check PCLMULQDQ bit */
726392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		gcm_init_clmul(ctx->Htable,ctx->H.u);
727392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->gmult = gcm_gmult_clmul;
728392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->ghash = gcm_ghash_clmul;
729392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return;
730392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
731392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#  endif
732392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	gcm_init_4bit(ctx->Htable,ctx->H.u);
733392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#  if	defined(GHASH_ASM_X86)			/* x86 only */
73404ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom#   if	defined(OPENSSL_IA32_SSE2)
735392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (OPENSSL_ia32cap_P[0]&(1<<25)) {	/* check SSE bit */
736392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#   else
737392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (OPENSSL_ia32cap_P[0]&(1<<23)) {	/* check MMX bit */
738392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#   endif
739392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->gmult = gcm_gmult_4bit_mmx;
740392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->ghash = gcm_ghash_4bit_mmx;
741392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	} else {
742392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->gmult = gcm_gmult_4bit_x86;
743392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->ghash = gcm_ghash_4bit_x86;
744392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
745392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#  else
746392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->gmult = gcm_gmult_4bit;
747392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->ghash = gcm_ghash_4bit;
748392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#  endif
749392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# elif	defined(GHASH_ASM_ARM)
7503f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root#  ifdef PMULL_CAPABLE
7513f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root	if (PMULL_CAPABLE) {
7523f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root		gcm_init_v8(ctx->Htable,ctx->H.u);
7533f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root		ctx->gmult = gcm_gmult_v8;
7543f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root		ctx->ghash = gcm_ghash_v8;
7553f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root	} else
7563f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root#  endif
7573f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root#  ifdef NEON_CAPABLE
7583f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root	if (NEON_CAPABLE) {
7593f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root		gcm_init_neon(ctx->Htable,ctx->H.u);
760392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->gmult = gcm_gmult_neon;
761392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->ghash = gcm_ghash_neon;
7623f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root	} else
7633f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root#  endif
7643f9e6ada2c9f7183a41081263585e6a70bbd9f59Kenny Root	{
765392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		gcm_init_4bit(ctx->Htable,ctx->H.u);
766392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->gmult = gcm_gmult_4bit;
767392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->ghash = gcm_ghash_4bit;
768392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
769392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# else
770392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	gcm_init_4bit(ctx->Htable,ctx->H.u);
771392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# endif
772392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
773392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
774392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
775392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromvoid CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx,const unsigned char *iv,size_t len)
776392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
777392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	const union { long one; char little; } is_endian = {1};
778392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	unsigned int ctr;
779392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef GCM_FUNCREF_4BIT
780392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*gcm_gmult_p)(u64 Xi[2],const u128 Htable[16])	= ctx->gmult;
781392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
782392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
783392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->Yi.u[0]  = 0;
784392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->Yi.u[1]  = 0;
785392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->Xi.u[0]  = 0;
786392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->Xi.u[1]  = 0;
787392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->len.u[0] = 0;	/* AAD length */
788392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->len.u[1] = 0;	/* message length */
789392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->ares = 0;
790392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->mres = 0;
791392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
792392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (len==12) {
793392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		memcpy(ctx->Yi.c,iv,12);
794392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->Yi.c[15]=1;
795392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr=1;
796392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
797392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else {
798392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		size_t i;
799392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		u64 len0 = len;
800392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
801392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while (len>=16) {
802392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			for (i=0; i<16; ++i) ctx->Yi.c[i] ^= iv[i];
803392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			GCM_MUL(ctx,Yi);
804392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			iv += 16;
805392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			len -= 16;
806392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
807392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (len) {
808392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			for (i=0; i<len; ++i) ctx->Yi.c[i] ^= iv[i];
809392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			GCM_MUL(ctx,Yi);
810392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
811392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		len0 <<= 3;
812392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (is_endian.little) {
813392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef BSWAP8
814392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.u[1]  ^= BSWAP8(len0);
815392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
816392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.c[8]  ^= (u8)(len0>>56);
817392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.c[9]  ^= (u8)(len0>>48);
818392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.c[10] ^= (u8)(len0>>40);
819392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.c[11] ^= (u8)(len0>>32);
820392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.c[12] ^= (u8)(len0>>24);
821392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.c[13] ^= (u8)(len0>>16);
822392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.c[14] ^= (u8)(len0>>8);
823392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.c[15] ^= (u8)(len0);
824392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
825392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
826392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
827392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.u[1]  ^= len0;
828392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
829392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		GCM_MUL(ctx,Yi);
830392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
831392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (is_endian.little)
8327f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#ifdef BSWAP4
8337f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root			ctr = BSWAP4(ctx->Yi.d[3]);
8347f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#else
835392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctr = GETU32(ctx->Yi.c+12);
8367f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#endif
837392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
838392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctr = ctx->Yi.d[3];
839392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
840392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
841392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	(*ctx->block)(ctx->Yi.c,ctx->EK0.c,ctx->key);
842392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	++ctr;
843392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (is_endian.little)
8447f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#ifdef BSWAP4
8457f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root		ctx->Yi.d[3] = BSWAP4(ctr);
8467f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#else
847392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		PUTU32(ctx->Yi.c+12,ctr);
8487f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#endif
849392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else
850392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->Yi.d[3] = ctr;
851392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
852392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
853392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromint CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx,const unsigned char *aad,size_t len)
854392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
855392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	size_t i;
856392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	unsigned int n;
857392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	u64 alen = ctx->len.u[0];
858392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef GCM_FUNCREF_4BIT
859392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*gcm_gmult_p)(u64 Xi[2],const u128 Htable[16])	= ctx->gmult;
860392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# ifdef GHASH
861392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*gcm_ghash_p)(u64 Xi[2],const u128 Htable[16],
862392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				const u8 *inp,size_t len)	= ctx->ghash;
863392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# endif
864392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
865392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
866392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (ctx->len.u[1]) return -2;
867392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
868392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	alen += len;
869392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (alen>(U64(1)<<61) || (sizeof(len)==8 && alen<len))
870392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return -1;
871392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->len.u[0] = alen;
872392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
873392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	n = ctx->ares;
874392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (n) {
875392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while (n && len) {
876392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Xi.c[n] ^= *(aad++);
877392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			--len;
878392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			n = (n+1)%16;
879392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
880392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (n==0) GCM_MUL(ctx,Xi);
881392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else {
882392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->ares = n;
883392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			return 0;
884392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
885392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
886392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
887392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef GHASH
888392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if ((i = (len&(size_t)-16))) {
889392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		GHASH(ctx,aad,i);
890392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		aad += i;
891392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		len -= i;
892392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
893392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
894392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	while (len>=16) {
895392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		for (i=0; i<16; ++i) ctx->Xi.c[i] ^= aad[i];
896392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		GCM_MUL(ctx,Xi);
897392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		aad += 16;
898392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		len -= 16;
899392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
900392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
901392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (len) {
902392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		n = (unsigned int)len;
903392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		for (i=0; i<len; ++i) ctx->Xi.c[i] ^= aad[i];
904392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
905392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
906392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->ares = n;
907392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return 0;
908392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
909392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
910392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromint CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx,
911392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		const unsigned char *in, unsigned char *out,
912392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		size_t len)
913392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
914392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	const union { long one; char little; } is_endian = {1};
915392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	unsigned int n, ctr;
916392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	size_t i;
917392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	u64        mlen  = ctx->len.u[1];
918392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	block128_f block = ctx->block;
919392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void      *key   = ctx->key;
920392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef GCM_FUNCREF_4BIT
921392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*gcm_gmult_p)(u64 Xi[2],const u128 Htable[16])	= ctx->gmult;
922392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# ifdef GHASH
923392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*gcm_ghash_p)(u64 Xi[2],const u128 Htable[16],
924392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				const u8 *inp,size_t len)	= ctx->ghash;
925392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# endif
926392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
927392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
928392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if 0
929392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	n = (unsigned int)mlen%16; /* alternative to ctx->mres */
930392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
931392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	mlen += len;
932392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (mlen>((U64(1)<<36)-32) || (sizeof(len)==8 && mlen<len))
933392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return -1;
934392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->len.u[1] = mlen;
935392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
936392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (ctx->ares) {
937392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* First call to encrypt finalizes GHASH(AAD) */
938392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		GCM_MUL(ctx,Xi);
939392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->ares = 0;
940392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
941392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
942392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (is_endian.little)
9437f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#ifdef BSWAP4
9447f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root		ctr = BSWAP4(ctx->Yi.d[3]);
9457f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#else
946392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr = GETU32(ctx->Yi.c+12);
9477f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#endif
948392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else
949392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr = ctx->Yi.d[3];
950392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
951392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	n = ctx->mres;
952392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if !defined(OPENSSL_SMALL_FOOTPRINT)
953392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (16%sizeof(size_t) == 0) do {	/* always true actually */
954392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (n) {
955392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			while (n && len) {
956392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Xi.c[n] ^= *(out++) = *(in++)^ctx->EKi.c[n];
957392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				--len;
958392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				n = (n+1)%16;
959392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
960392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (n==0) GCM_MUL(ctx,Xi);
961392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else {
962392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->mres = n;
963392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				return 0;
964392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
965392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
966392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(STRICT_ALIGNMENT)
967392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (((size_t)in|(size_t)out)%sizeof(size_t) != 0)
968392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			break;
969392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
970392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(GHASH) && defined(GHASH_CHUNK)
971392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while (len>=GHASH_CHUNK) {
972392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    size_t j=GHASH_CHUNK;
973392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
974392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    while (j) {
975ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root		    	size_t *out_t=(size_t *)out;
976ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root		    	const size_t *in_t=(const size_t *)in;
977ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root
978392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(*block)(ctx->Yi.c,ctx->EKi.c,key);
979392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			++ctr;
980392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (is_endian.little)
9817f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#ifdef BSWAP4
9827f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root				ctx->Yi.d[3] = BSWAP4(ctr);
9837f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#else
984392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				PUTU32(ctx->Yi.c+12,ctr);
9857f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#endif
986392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
987392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Yi.d[3] = ctr;
988ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			for (i=0; i<16/sizeof(size_t); ++i)
989ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root				out_t[i] = in_t[i] ^ ctx->EKi.t[i];
990392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			out += 16;
991392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			in  += 16;
992392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			j   -= 16;
993392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    }
994392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    GHASH(ctx,out-GHASH_CHUNK,GHASH_CHUNK);
995392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    len -= GHASH_CHUNK;
996392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
997392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if ((i = (len&(size_t)-16))) {
998392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    size_t j=i;
999392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1000392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    while (len>=16) {
1001ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root		    	size_t *out_t=(size_t *)out;
1002ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root		    	const size_t *in_t=(const size_t *)in;
1003ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root
1004392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(*block)(ctx->Yi.c,ctx->EKi.c,key);
1005392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			++ctr;
1006392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (is_endian.little)
10077f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#ifdef BSWAP4
10087f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root				ctx->Yi.d[3] = BSWAP4(ctr);
10097f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#else
1010392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				PUTU32(ctx->Yi.c+12,ctr);
10117f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#endif
1012392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
1013392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Yi.d[3] = ctr;
1014ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			for (i=0; i<16/sizeof(size_t); ++i)
1015ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root				out_t[i] = in_t[i] ^ ctx->EKi.t[i];
1016392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			out += 16;
1017392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			in  += 16;
1018392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			len -= 16;
1019392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    }
1020392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    GHASH(ctx,out-j,j);
1021392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1022392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
1023392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while (len>=16) {
1024ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root		    	size_t *out_t=(size_t *)out;
1025ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root		    	const size_t *in_t=(const size_t *)in;
1026ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root
1027392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(*block)(ctx->Yi.c,ctx->EKi.c,key);
1028392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			++ctr;
1029392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (is_endian.little)
10307f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#ifdef BSWAP4
10317f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root				ctx->Yi.d[3] = BSWAP4(ctr);
10327f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#else
1033392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				PUTU32(ctx->Yi.c+12,ctr);
10347f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#endif
1035392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
1036392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Yi.d[3] = ctr;
1037ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			for (i=0; i<16/sizeof(size_t); ++i)
1038ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root				ctx->Xi.t[i] ^=
1039ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root				out_t[i] = in_t[i]^ctx->EKi.t[i];
1040392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			GCM_MUL(ctx,Xi);
1041392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			out += 16;
1042392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			in  += 16;
1043392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			len -= 16;
1044392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1045392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1046392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (len) {
1047392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(*block)(ctx->Yi.c,ctx->EKi.c,key);
1048392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			++ctr;
1049392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (is_endian.little)
10507f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#ifdef BSWAP4
10517f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root				ctx->Yi.d[3] = BSWAP4(ctr);
10527f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#else
1053392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				PUTU32(ctx->Yi.c+12,ctr);
10547f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#endif
1055392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
1056392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Yi.d[3] = ctr;
1057392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			while (len--) {
1058392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Xi.c[n] ^= out[n] = in[n]^ctx->EKi.c[n];
1059392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				++n;
1060392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1061392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1062392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1063392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->mres = n;
1064392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return 0;
1065392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	} while(0);
1066392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1067392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	for (i=0;i<len;++i) {
1068392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (n==0) {
1069392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(*block)(ctx->Yi.c,ctx->EKi.c,key);
1070392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			++ctr;
1071392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (is_endian.little)
10727f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#ifdef BSWAP4
10737f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root				ctx->Yi.d[3] = BSWAP4(ctr);
10747f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#else
1075392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				PUTU32(ctx->Yi.c+12,ctr);
10767f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#endif
1077392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
1078392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Yi.d[3] = ctr;
1079392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1080392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->Xi.c[n] ^= out[i] = in[i]^ctx->EKi.c[n];
1081392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		n = (n+1)%16;
1082392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (n==0)
1083392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			GCM_MUL(ctx,Xi);
1084392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1085392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1086392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->mres = n;
1087392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return 0;
1088392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
1089392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1090392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromint CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx,
1091392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		const unsigned char *in, unsigned char *out,
1092392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		size_t len)
1093392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
1094392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	const union { long one; char little; } is_endian = {1};
1095392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	unsigned int n, ctr;
1096392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	size_t i;
1097392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	u64        mlen  = ctx->len.u[1];
1098392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	block128_f block = ctx->block;
1099392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void      *key   = ctx->key;
1100392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef GCM_FUNCREF_4BIT
1101392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*gcm_gmult_p)(u64 Xi[2],const u128 Htable[16])	= ctx->gmult;
1102392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# ifdef GHASH
1103392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*gcm_ghash_p)(u64 Xi[2],const u128 Htable[16],
1104392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				const u8 *inp,size_t len)	= ctx->ghash;
1105392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# endif
1106392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1107392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1108392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	mlen += len;
1109392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (mlen>((U64(1)<<36)-32) || (sizeof(len)==8 && mlen<len))
1110392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return -1;
1111392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->len.u[1] = mlen;
1112392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1113392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (ctx->ares) {
1114392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* First call to decrypt finalizes GHASH(AAD) */
1115392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		GCM_MUL(ctx,Xi);
1116392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->ares = 0;
1117392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1118392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1119392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (is_endian.little)
11207f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#ifdef BSWAP4
11217f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root		ctr = BSWAP4(ctx->Yi.d[3]);
11227f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#else
1123392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr = GETU32(ctx->Yi.c+12);
11247f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#endif
1125392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else
1126392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr = ctx->Yi.d[3];
1127392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1128392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	n = ctx->mres;
1129392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if !defined(OPENSSL_SMALL_FOOTPRINT)
1130392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (16%sizeof(size_t) == 0) do {	/* always true actually */
1131392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (n) {
1132392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			while (n && len) {
1133392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				u8 c = *(in++);
1134392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				*(out++) = c^ctx->EKi.c[n];
1135392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Xi.c[n] ^= c;
1136392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				--len;
1137392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				n = (n+1)%16;
1138392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1139392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (n==0) GCM_MUL (ctx,Xi);
1140392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else {
1141392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->mres = n;
1142392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				return 0;
1143392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1144392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1145392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(STRICT_ALIGNMENT)
1146392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (((size_t)in|(size_t)out)%sizeof(size_t) != 0)
1147392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			break;
1148392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1149392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(GHASH) && defined(GHASH_CHUNK)
1150392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while (len>=GHASH_CHUNK) {
1151392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    size_t j=GHASH_CHUNK;
1152392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1153392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    GHASH(ctx,in,GHASH_CHUNK);
1154392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    while (j) {
1155ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root		    	size_t *out_t=(size_t *)out;
1156ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root		    	const size_t *in_t=(const size_t *)in;
1157ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root
1158392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(*block)(ctx->Yi.c,ctx->EKi.c,key);
1159392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			++ctr;
1160392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (is_endian.little)
11617f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#ifdef BSWAP4
11627f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root				ctx->Yi.d[3] = BSWAP4(ctr);
11637f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#else
1164392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				PUTU32(ctx->Yi.c+12,ctr);
11657f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#endif
1166392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
1167392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Yi.d[3] = ctr;
1168ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			for (i=0; i<16/sizeof(size_t); ++i)
1169ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root				out_t[i] = in_t[i]^ctx->EKi.t[i];
1170392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			out += 16;
1171392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			in  += 16;
1172392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			j   -= 16;
1173392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    }
1174392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    len -= GHASH_CHUNK;
1175392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1176392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if ((i = (len&(size_t)-16))) {
1177392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    GHASH(ctx,in,i);
1178392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    while (len>=16) {
1179ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root		    	size_t *out_t=(size_t *)out;
1180ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root		    	const size_t *in_t=(const size_t *)in;
1181ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root
1182392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(*block)(ctx->Yi.c,ctx->EKi.c,key);
1183392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			++ctr;
1184392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (is_endian.little)
11857f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#ifdef BSWAP4
11867f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root				ctx->Yi.d[3] = BSWAP4(ctr);
11877f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#else
1188392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				PUTU32(ctx->Yi.c+12,ctr);
11897f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#endif
1190392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
1191392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Yi.d[3] = ctr;
1192ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			for (i=0; i<16/sizeof(size_t); ++i)
1193ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root				out_t[i] = in_t[i]^ctx->EKi.t[i];
1194392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			out += 16;
1195392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			in  += 16;
1196392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			len -= 16;
1197392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		    }
1198392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1199392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
1200392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while (len>=16) {
1201ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root		    	size_t *out_t=(size_t *)out;
1202ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root		    	const size_t *in_t=(const size_t *)in;
1203ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root
1204392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(*block)(ctx->Yi.c,ctx->EKi.c,key);
1205392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			++ctr;
1206392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (is_endian.little)
12077f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#ifdef BSWAP4
12087f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root				ctx->Yi.d[3] = BSWAP4(ctr);
12097f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#else
1210392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				PUTU32(ctx->Yi.c+12,ctr);
12117f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#endif
1212392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
1213392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Yi.d[3] = ctr;
1214ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			for (i=0; i<16/sizeof(size_t); ++i) {
1215ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root				size_t c = in[i];
1216ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root				out[i] = c^ctx->EKi.t[i];
1217ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root				ctx->Xi.t[i] ^= c;
1218392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1219392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			GCM_MUL(ctx,Xi);
1220392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			out += 16;
1221392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			in  += 16;
1222392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			len -= 16;
1223392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1224392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1225392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (len) {
1226392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(*block)(ctx->Yi.c,ctx->EKi.c,key);
1227392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			++ctr;
1228392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (is_endian.little)
12297f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#ifdef BSWAP4
12307f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root				ctx->Yi.d[3] = BSWAP4(ctr);
12317f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#else
1232392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				PUTU32(ctx->Yi.c+12,ctr);
12337f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#endif
1234392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
1235392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Yi.d[3] = ctr;
1236392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			while (len--) {
1237392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				u8 c = in[n];
1238392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Xi.c[n] ^= c;
1239392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				out[n] = c^ctx->EKi.c[n];
1240392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				++n;
1241392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
1242392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1243392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1244392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->mres = n;
1245392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return 0;
1246392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	} while(0);
1247392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1248392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	for (i=0;i<len;++i) {
1249392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		u8 c;
1250392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (n==0) {
1251392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(*block)(ctx->Yi.c,ctx->EKi.c,key);
1252392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			++ctr;
1253392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (is_endian.little)
12547f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#ifdef BSWAP4
12557f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root				ctx->Yi.d[3] = BSWAP4(ctr);
12567f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#else
1257392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				PUTU32(ctx->Yi.c+12,ctr);
12587f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#endif
1259392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
1260392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ctx->Yi.d[3] = ctr;
1261392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1262392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		c = in[i];
1263392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		out[i] = c^ctx->EKi.c[n];
1264392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->Xi.c[n] ^= c;
1265392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		n = (n+1)%16;
1266392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (n==0)
1267392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			GCM_MUL(ctx,Xi);
1268392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1269392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1270392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->mres = n;
1271392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return 0;
1272392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
1273392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1274392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromint CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx,
1275392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		const unsigned char *in, unsigned char *out,
1276392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		size_t len, ctr128_f stream)
1277392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
1278392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	const union { long one; char little; } is_endian = {1};
1279392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	unsigned int n, ctr;
1280392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	size_t i;
1281392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	u64   mlen = ctx->len.u[1];
1282392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void *key  = ctx->key;
1283392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef GCM_FUNCREF_4BIT
1284392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*gcm_gmult_p)(u64 Xi[2],const u128 Htable[16])	= ctx->gmult;
1285392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# ifdef GHASH
1286392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*gcm_ghash_p)(u64 Xi[2],const u128 Htable[16],
1287392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				const u8 *inp,size_t len)	= ctx->ghash;
1288392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# endif
1289392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1290392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1291392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	mlen += len;
1292392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (mlen>((U64(1)<<36)-32) || (sizeof(len)==8 && mlen<len))
1293392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return -1;
1294392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->len.u[1] = mlen;
1295392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1296392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (ctx->ares) {
1297392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* First call to encrypt finalizes GHASH(AAD) */
1298392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		GCM_MUL(ctx,Xi);
1299392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->ares = 0;
1300392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1301392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1302392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (is_endian.little)
13037f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#ifdef BSWAP4
13047f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root		ctr = BSWAP4(ctx->Yi.d[3]);
13057f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#else
1306392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr = GETU32(ctx->Yi.c+12);
13077f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#endif
1308392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else
1309392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr = ctx->Yi.d[3];
1310392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1311392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	n = ctx->mres;
1312392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (n) {
1313392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while (n && len) {
1314392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Xi.c[n] ^= *(out++) = *(in++)^ctx->EKi.c[n];
1315392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			--len;
1316392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			n = (n+1)%16;
1317392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1318392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (n==0) GCM_MUL(ctx,Xi);
1319392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else {
1320392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->mres = n;
1321392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			return 0;
1322392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1323392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1324392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT)
1325392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	while (len>=GHASH_CHUNK) {
1326392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		(*stream)(in,out,GHASH_CHUNK/16,key,ctx->Yi.c);
1327392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr += GHASH_CHUNK/16;
1328392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (is_endian.little)
13297f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#ifdef BSWAP4
13307f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root			ctx->Yi.d[3] = BSWAP4(ctr);
13317f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#else
1332392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			PUTU32(ctx->Yi.c+12,ctr);
13337f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#endif
1334392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
1335392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.d[3] = ctr;
1336392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		GHASH(ctx,out,GHASH_CHUNK);
1337392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		out += GHASH_CHUNK;
1338392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		in  += GHASH_CHUNK;
1339392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		len -= GHASH_CHUNK;
1340392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1341392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1342392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if ((i = (len&(size_t)-16))) {
1343392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		size_t j=i/16;
1344392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1345392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		(*stream)(in,out,j,key,ctx->Yi.c);
1346392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr += (unsigned int)j;
1347392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (is_endian.little)
13487f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#ifdef BSWAP4
13497f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root			ctx->Yi.d[3] = BSWAP4(ctr);
13507f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#else
1351392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			PUTU32(ctx->Yi.c+12,ctr);
13527f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#endif
1353392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
1354392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.d[3] = ctr;
1355392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		in  += i;
1356392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		len -= i;
1357392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(GHASH)
1358392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		GHASH(ctx,out,i);
1359392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		out += i;
1360392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
1361392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while (j--) {
1362392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			for (i=0;i<16;++i) ctx->Xi.c[i] ^= out[i];
1363392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			GCM_MUL(ctx,Xi);
1364392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			out += 16;
1365392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1366392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1367392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1368392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (len) {
1369392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		(*ctx->block)(ctx->Yi.c,ctx->EKi.c,key);
1370392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		++ctr;
1371392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (is_endian.little)
13727f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#ifdef BSWAP4
13737f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root			ctx->Yi.d[3] = BSWAP4(ctr);
13747f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#else
1375392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			PUTU32(ctx->Yi.c+12,ctr);
13767f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#endif
1377392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
1378392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.d[3] = ctr;
1379392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while (len--) {
1380392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Xi.c[n] ^= out[n] = in[n]^ctx->EKi.c[n];
1381392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			++n;
1382392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1383392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1384392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1385392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->mres = n;
1386392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return 0;
1387392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
1388392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1389392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromint CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx,
1390392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		const unsigned char *in, unsigned char *out,
1391392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		size_t len,ctr128_f stream)
1392392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
1393392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	const union { long one; char little; } is_endian = {1};
1394392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	unsigned int n, ctr;
1395392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	size_t i;
1396392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	u64   mlen = ctx->len.u[1];
1397392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void *key  = ctx->key;
1398392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef GCM_FUNCREF_4BIT
1399392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*gcm_gmult_p)(u64 Xi[2],const u128 Htable[16])	= ctx->gmult;
1400392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# ifdef GHASH
1401392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*gcm_ghash_p)(u64 Xi[2],const u128 Htable[16],
1402392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				const u8 *inp,size_t len)	= ctx->ghash;
1403392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom# endif
1404392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1405392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1406392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	mlen += len;
1407392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (mlen>((U64(1)<<36)-32) || (sizeof(len)==8 && mlen<len))
1408392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return -1;
1409392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->len.u[1] = mlen;
1410392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1411392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (ctx->ares) {
1412392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* First call to decrypt finalizes GHASH(AAD) */
1413392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		GCM_MUL(ctx,Xi);
1414392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->ares = 0;
1415392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1416392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1417392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (is_endian.little)
14187f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#ifdef BSWAP4
14197f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root		ctr = BSWAP4(ctx->Yi.d[3]);
14207f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#else
1421392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr = GETU32(ctx->Yi.c+12);
14227f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#endif
1423392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else
1424392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr = ctx->Yi.d[3];
1425392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1426392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	n = ctx->mres;
1427392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (n) {
1428392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while (n && len) {
1429392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			u8 c = *(in++);
1430392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			*(out++) = c^ctx->EKi.c[n];
1431392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Xi.c[n] ^= c;
1432392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			--len;
1433392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			n = (n+1)%16;
1434392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1435392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (n==0) GCM_MUL (ctx,Xi);
1436392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else {
1437392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->mres = n;
1438392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			return 0;
1439392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1440392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1441392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(GHASH) && !defined(OPENSSL_SMALL_FOOTPRINT)
1442392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	while (len>=GHASH_CHUNK) {
1443392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		GHASH(ctx,in,GHASH_CHUNK);
1444392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		(*stream)(in,out,GHASH_CHUNK/16,key,ctx->Yi.c);
1445392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr += GHASH_CHUNK/16;
1446392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (is_endian.little)
14477f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#ifdef BSWAP4
14487f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root			ctx->Yi.d[3] = BSWAP4(ctr);
14497f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#else
1450392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			PUTU32(ctx->Yi.c+12,ctr);
14517f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#endif
1452392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
1453392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.d[3] = ctr;
1454392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		out += GHASH_CHUNK;
1455392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		in  += GHASH_CHUNK;
1456392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		len -= GHASH_CHUNK;
1457392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1458392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1459392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if ((i = (len&(size_t)-16))) {
1460392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		size_t j=i/16;
1461392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1462392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(GHASH)
1463392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		GHASH(ctx,in,i);
1464392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
1465392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while (j--) {
1466392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			size_t k;
1467392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			for (k=0;k<16;++k) ctx->Xi.c[k] ^= in[k];
1468392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			GCM_MUL(ctx,Xi);
1469392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			in += 16;
1470392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1471392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		j   = i/16;
1472392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		in -= i;
1473392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1474392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		(*stream)(in,out,j,key,ctx->Yi.c);
1475392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctr += (unsigned int)j;
1476392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (is_endian.little)
14777f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#ifdef BSWAP4
14787f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root			ctx->Yi.d[3] = BSWAP4(ctr);
14797f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#else
1480392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			PUTU32(ctx->Yi.c+12,ctr);
14817f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#endif
1482392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
1483392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.d[3] = ctr;
1484392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		out += i;
1485392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		in  += i;
1486392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		len -= i;
1487392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1488392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (len) {
1489392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		(*ctx->block)(ctx->Yi.c,ctx->EKi.c,key);
1490392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		++ctr;
1491392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (is_endian.little)
14927f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#ifdef BSWAP4
14937f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root			ctx->Yi.d[3] = BSWAP4(ctr);
14947f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#else
1495392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			PUTU32(ctx->Yi.c+12,ctr);
14967f7ea2d72f2e316ba518e82f06513e3477840c15Kenny Root#endif
1497392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		else
1498392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Yi.d[3] = ctr;
1499392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while (len--) {
1500392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			u8 c = in[n];
1501392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx->Xi.c[n] ^= c;
1502392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			out[n] = c^ctx->EKi.c[n];
1503392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			++n;
1504392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
1505392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1506392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1507392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->mres = n;
1508392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return 0;
1509392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
1510392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1511392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromint CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx,const unsigned char *tag,
1512392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			size_t len)
1513392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
1514392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	const union { long one; char little; } is_endian = {1};
1515392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	u64 alen = ctx->len.u[0]<<3;
1516392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	u64 clen = ctx->len.u[1]<<3;
1517392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef GCM_FUNCREF_4BIT
1518392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	void (*gcm_gmult_p)(u64 Xi[2],const u128 Htable[16])	= ctx->gmult;
1519392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1520392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
152104ef91b390dfcc6125913e2f2af502d23d7a5112Brian Carlstrom	if (ctx->mres || ctx->ares)
1522392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		GCM_MUL(ctx,Xi);
1523392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1524392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (is_endian.little) {
1525392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef BSWAP8
1526392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		alen = BSWAP8(alen);
1527392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		clen = BSWAP8(clen);
1528392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#else
1529392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		u8 *p = ctx->len.c;
1530392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1531392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->len.u[0] = alen;
1532392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx->len.u[1] = clen;
1533392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1534392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		alen = (u64)GETU32(p)  <<32|GETU32(p+4);
1535392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		clen = (u64)GETU32(p+8)<<32|GETU32(p+12);
1536392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1537392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1538392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1539392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->Xi.u[0] ^= alen;
1540392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->Xi.u[1] ^= clen;
1541392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	GCM_MUL(ctx,Xi);
1542392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1543392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->Xi.u[0] ^= ctx->EK0.u[0];
1544392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctx->Xi.u[1] ^= ctx->EK0.u[1];
1545392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1546392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (tag && len<=sizeof(ctx->Xi))
1547392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return memcmp(ctx->Xi.c,tag,len);
1548392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else
1549392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return -1;
1550392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
1551392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1552392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromvoid CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, unsigned char *tag, size_t len)
1553392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
1554392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	CRYPTO_gcm128_finish(ctx, NULL, 0);
1555392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	memcpy(tag, ctx->Xi.c, len<=sizeof(ctx->Xi.c)?len:sizeof(ctx->Xi.c));
1556392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
1557392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1558392aa7cc7d2b122614c5393c3e357da07fd07af3Brian CarlstromGCM128_CONTEXT *CRYPTO_gcm128_new(void *key, block128_f block)
1559392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
1560392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	GCM128_CONTEXT *ret;
1561392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1562392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if ((ret = (GCM128_CONTEXT *)OPENSSL_malloc(sizeof(GCM128_CONTEXT))))
1563392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		CRYPTO_gcm128_init(ret,key,block);
1564392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1565392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return ret;
1566392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
1567392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1568392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromvoid CRYPTO_gcm128_release(GCM128_CONTEXT *ctx)
1569392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
1570392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (ctx) {
1571392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		OPENSSL_cleanse(ctx,sizeof(*ctx));
1572392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		OPENSSL_free(ctx);
1573392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1574392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
1575392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1576392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#if defined(SELFTEST)
1577392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#include <stdio.h>
1578392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#include <openssl/aes.h>
1579392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1580392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 1 */
1581392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	K1[16],
1582392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		*P1=NULL,
1583392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		*A1=NULL,
1584392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		IV1[12],
1585392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		*C1=NULL,
1586392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T1[]=  {0x58,0xe2,0xfc,0xce,0xfa,0x7e,0x30,0x61,0x36,0x7f,0x1d,0x57,0xa4,0xe7,0x45,0x5a};
1587392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1588392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 2 */
1589392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define K2 K1
1590392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define A2 A1
1591392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define IV2 IV1
1592392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	P2[16],
1593392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C2[]=  {0x03,0x88,0xda,0xce,0x60,0xb6,0xa3,0x92,0xf3,0x28,0xc2,0xb9,0x71,0xb2,0xfe,0x78},
1594392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T2[]=  {0xab,0x6e,0x47,0xd4,0x2c,0xec,0x13,0xbd,0xf5,0x3a,0x67,0xb2,0x12,0x57,0xbd,0xdf};
1595392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1596392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 3 */
1597392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define A3 A2
1598392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	K3[]=  {0xfe,0xff,0xe9,0x92,0x86,0x65,0x73,0x1c,0x6d,0x6a,0x8f,0x94,0x67,0x30,0x83,0x08},
1599392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		P3[]=  {0xd9,0x31,0x32,0x25,0xf8,0x84,0x06,0xe5,0xa5,0x59,0x09,0xc5,0xaf,0xf5,0x26,0x9a,
1600392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x86,0xa7,0xa9,0x53,0x15,0x34,0xf7,0xda,0x2e,0x4c,0x30,0x3d,0x8a,0x31,0x8a,0x72,
1601392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x1c,0x3c,0x0c,0x95,0x95,0x68,0x09,0x53,0x2f,0xcf,0x0e,0x24,0x49,0xa6,0xb5,0x25,
1602392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xb1,0x6a,0xed,0xf5,0xaa,0x0d,0xe6,0x57,0xba,0x63,0x7b,0x39,0x1a,0xaf,0xd2,0x55},
1603392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		IV3[]= {0xca,0xfe,0xba,0xbe,0xfa,0xce,0xdb,0xad,0xde,0xca,0xf8,0x88},
1604392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C3[]=  {0x42,0x83,0x1e,0xc2,0x21,0x77,0x74,0x24,0x4b,0x72,0x21,0xb7,0x84,0xd0,0xd4,0x9c,
1605392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xe3,0xaa,0x21,0x2f,0x2c,0x02,0xa4,0xe0,0x35,0xc1,0x7e,0x23,0x29,0xac,0xa1,0x2e,
1606392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x21,0xd5,0x14,0xb2,0x54,0x66,0x93,0x1c,0x7d,0x8f,0x6a,0x5a,0xac,0x84,0xaa,0x05,
1607392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x1b,0xa3,0x0b,0x39,0x6a,0x0a,0xac,0x97,0x3d,0x58,0xe0,0x91,0x47,0x3f,0x59,0x85},
1608392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T3[]=  {0x4d,0x5c,0x2a,0xf3,0x27,0xcd,0x64,0xa6,0x2c,0xf3,0x5a,0xbd,0x2b,0xa6,0xfa,0xb4};
1609392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1610392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 4 */
1611392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define K4 K3
1612392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define IV4 IV3
1613392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	P4[]=  {0xd9,0x31,0x32,0x25,0xf8,0x84,0x06,0xe5,0xa5,0x59,0x09,0xc5,0xaf,0xf5,0x26,0x9a,
1614392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x86,0xa7,0xa9,0x53,0x15,0x34,0xf7,0xda,0x2e,0x4c,0x30,0x3d,0x8a,0x31,0x8a,0x72,
1615392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x1c,0x3c,0x0c,0x95,0x95,0x68,0x09,0x53,0x2f,0xcf,0x0e,0x24,0x49,0xa6,0xb5,0x25,
1616392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xb1,0x6a,0xed,0xf5,0xaa,0x0d,0xe6,0x57,0xba,0x63,0x7b,0x39},
1617392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		A4[]=  {0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef,0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef,
1618392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xab,0xad,0xda,0xd2},
1619392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C4[]=  {0x42,0x83,0x1e,0xc2,0x21,0x77,0x74,0x24,0x4b,0x72,0x21,0xb7,0x84,0xd0,0xd4,0x9c,
1620392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xe3,0xaa,0x21,0x2f,0x2c,0x02,0xa4,0xe0,0x35,0xc1,0x7e,0x23,0x29,0xac,0xa1,0x2e,
1621392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x21,0xd5,0x14,0xb2,0x54,0x66,0x93,0x1c,0x7d,0x8f,0x6a,0x5a,0xac,0x84,0xaa,0x05,
1622392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x1b,0xa3,0x0b,0x39,0x6a,0x0a,0xac,0x97,0x3d,0x58,0xe0,0x91},
1623392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T4[]=  {0x5b,0xc9,0x4f,0xbc,0x32,0x21,0xa5,0xdb,0x94,0xfa,0xe9,0x5a,0xe7,0x12,0x1a,0x47};
1624392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1625392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 5 */
1626392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define K5 K4
1627392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define P5 P4
1628392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define A5 A4
1629392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	IV5[]= {0xca,0xfe,0xba,0xbe,0xfa,0xce,0xdb,0xad},
1630392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C5[]=  {0x61,0x35,0x3b,0x4c,0x28,0x06,0x93,0x4a,0x77,0x7f,0xf5,0x1f,0xa2,0x2a,0x47,0x55,
1631392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x69,0x9b,0x2a,0x71,0x4f,0xcd,0xc6,0xf8,0x37,0x66,0xe5,0xf9,0x7b,0x6c,0x74,0x23,
1632392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x73,0x80,0x69,0x00,0xe4,0x9f,0x24,0xb2,0x2b,0x09,0x75,0x44,0xd4,0x89,0x6b,0x42,
1633392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x49,0x89,0xb5,0xe1,0xeb,0xac,0x0f,0x07,0xc2,0x3f,0x45,0x98},
1634392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T5[]=  {0x36,0x12,0xd2,0xe7,0x9e,0x3b,0x07,0x85,0x56,0x1b,0xe1,0x4a,0xac,0xa2,0xfc,0xcb};
1635392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1636392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 6 */
1637392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define K6 K5
1638392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define P6 P5
1639392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define A6 A5
1640392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	IV6[]= {0x93,0x13,0x22,0x5d,0xf8,0x84,0x06,0xe5,0x55,0x90,0x9c,0x5a,0xff,0x52,0x69,0xaa,
1641392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x6a,0x7a,0x95,0x38,0x53,0x4f,0x7d,0xa1,0xe4,0xc3,0x03,0xd2,0xa3,0x18,0xa7,0x28,
1642392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xc3,0xc0,0xc9,0x51,0x56,0x80,0x95,0x39,0xfc,0xf0,0xe2,0x42,0x9a,0x6b,0x52,0x54,
1643392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x16,0xae,0xdb,0xf5,0xa0,0xde,0x6a,0x57,0xa6,0x37,0xb3,0x9b},
1644392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C6[]=  {0x8c,0xe2,0x49,0x98,0x62,0x56,0x15,0xb6,0x03,0xa0,0x33,0xac,0xa1,0x3f,0xb8,0x94,
1645392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xbe,0x91,0x12,0xa5,0xc3,0xa2,0x11,0xa8,0xba,0x26,0x2a,0x3c,0xca,0x7e,0x2c,0xa7,
1646392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x01,0xe4,0xa9,0xa4,0xfb,0xa4,0x3c,0x90,0xcc,0xdc,0xb2,0x81,0xd4,0x8c,0x7c,0x6f,
1647392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xd6,0x28,0x75,0xd2,0xac,0xa4,0x17,0x03,0x4c,0x34,0xae,0xe5},
1648392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T6[]=  {0x61,0x9c,0xc5,0xae,0xff,0xfe,0x0b,0xfa,0x46,0x2a,0xf4,0x3c,0x16,0x99,0xd0,0x50};
1649392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1650392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 7 */
1651392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8 K7[24],
1652392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		*P7=NULL,
1653392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		*A7=NULL,
1654392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		IV7[12],
1655392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		*C7=NULL,
1656392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T7[]=  {0xcd,0x33,0xb2,0x8a,0xc7,0x73,0xf7,0x4b,0xa0,0x0e,0xd1,0xf3,0x12,0x57,0x24,0x35};
1657392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1658392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 8 */
1659392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define K8 K7
1660392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define IV8 IV7
1661392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define A8 A7
1662392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	P8[16],
1663392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C8[]=  {0x98,0xe7,0x24,0x7c,0x07,0xf0,0xfe,0x41,0x1c,0x26,0x7e,0x43,0x84,0xb0,0xf6,0x00},
1664392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T8[]=  {0x2f,0xf5,0x8d,0x80,0x03,0x39,0x27,0xab,0x8e,0xf4,0xd4,0x58,0x75,0x14,0xf0,0xfb};
1665392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1666392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 9 */
1667392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define A9 A8
1668392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	K9[]=  {0xfe,0xff,0xe9,0x92,0x86,0x65,0x73,0x1c,0x6d,0x6a,0x8f,0x94,0x67,0x30,0x83,0x08,
1669392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xfe,0xff,0xe9,0x92,0x86,0x65,0x73,0x1c},
1670392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		P9[]=  {0xd9,0x31,0x32,0x25,0xf8,0x84,0x06,0xe5,0xa5,0x59,0x09,0xc5,0xaf,0xf5,0x26,0x9a,
1671392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x86,0xa7,0xa9,0x53,0x15,0x34,0xf7,0xda,0x2e,0x4c,0x30,0x3d,0x8a,0x31,0x8a,0x72,
1672392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x1c,0x3c,0x0c,0x95,0x95,0x68,0x09,0x53,0x2f,0xcf,0x0e,0x24,0x49,0xa6,0xb5,0x25,
1673392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xb1,0x6a,0xed,0xf5,0xaa,0x0d,0xe6,0x57,0xba,0x63,0x7b,0x39,0x1a,0xaf,0xd2,0x55},
1674392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		IV9[]= {0xca,0xfe,0xba,0xbe,0xfa,0xce,0xdb,0xad,0xde,0xca,0xf8,0x88},
1675392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C9[]=  {0x39,0x80,0xca,0x0b,0x3c,0x00,0xe8,0x41,0xeb,0x06,0xfa,0xc4,0x87,0x2a,0x27,0x57,
1676392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x85,0x9e,0x1c,0xea,0xa6,0xef,0xd9,0x84,0x62,0x85,0x93,0xb4,0x0c,0xa1,0xe1,0x9c,
1677392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x7d,0x77,0x3d,0x00,0xc1,0x44,0xc5,0x25,0xac,0x61,0x9d,0x18,0xc8,0x4a,0x3f,0x47,
1678392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x18,0xe2,0x44,0x8b,0x2f,0xe3,0x24,0xd9,0xcc,0xda,0x27,0x10,0xac,0xad,0xe2,0x56},
1679392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T9[]=  {0x99,0x24,0xa7,0xc8,0x58,0x73,0x36,0xbf,0xb1,0x18,0x02,0x4d,0xb8,0x67,0x4a,0x14};
1680392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1681392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 10 */
1682392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define K10 K9
1683392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define IV10 IV9
1684392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	P10[]= {0xd9,0x31,0x32,0x25,0xf8,0x84,0x06,0xe5,0xa5,0x59,0x09,0xc5,0xaf,0xf5,0x26,0x9a,
1685392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x86,0xa7,0xa9,0x53,0x15,0x34,0xf7,0xda,0x2e,0x4c,0x30,0x3d,0x8a,0x31,0x8a,0x72,
1686392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x1c,0x3c,0x0c,0x95,0x95,0x68,0x09,0x53,0x2f,0xcf,0x0e,0x24,0x49,0xa6,0xb5,0x25,
1687392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xb1,0x6a,0xed,0xf5,0xaa,0x0d,0xe6,0x57,0xba,0x63,0x7b,0x39},
1688392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		A10[]= {0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef,0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef,
1689392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xab,0xad,0xda,0xd2},
1690392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C10[]= {0x39,0x80,0xca,0x0b,0x3c,0x00,0xe8,0x41,0xeb,0x06,0xfa,0xc4,0x87,0x2a,0x27,0x57,
1691392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x85,0x9e,0x1c,0xea,0xa6,0xef,0xd9,0x84,0x62,0x85,0x93,0xb4,0x0c,0xa1,0xe1,0x9c,
1692392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x7d,0x77,0x3d,0x00,0xc1,0x44,0xc5,0x25,0xac,0x61,0x9d,0x18,0xc8,0x4a,0x3f,0x47,
1693392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x18,0xe2,0x44,0x8b,0x2f,0xe3,0x24,0xd9,0xcc,0xda,0x27,0x10},
1694392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T10[]= {0x25,0x19,0x49,0x8e,0x80,0xf1,0x47,0x8f,0x37,0xba,0x55,0xbd,0x6d,0x27,0x61,0x8c};
1695392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1696392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 11 */
1697392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define K11 K10
1698392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define P11 P10
1699392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define A11 A10
1700392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	IV11[]={0xca,0xfe,0xba,0xbe,0xfa,0xce,0xdb,0xad},
1701392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C11[]= {0x0f,0x10,0xf5,0x99,0xae,0x14,0xa1,0x54,0xed,0x24,0xb3,0x6e,0x25,0x32,0x4d,0xb8,
1702392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xc5,0x66,0x63,0x2e,0xf2,0xbb,0xb3,0x4f,0x83,0x47,0x28,0x0f,0xc4,0x50,0x70,0x57,
1703392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xfd,0xdc,0x29,0xdf,0x9a,0x47,0x1f,0x75,0xc6,0x65,0x41,0xd4,0xd4,0xda,0xd1,0xc9,
1704392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xe9,0x3a,0x19,0xa5,0x8e,0x8b,0x47,0x3f,0xa0,0xf0,0x62,0xf7},
1705392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T11[]= {0x65,0xdc,0xc5,0x7f,0xcf,0x62,0x3a,0x24,0x09,0x4f,0xcc,0xa4,0x0d,0x35,0x33,0xf8};
1706392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1707392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 12 */
1708392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define K12 K11
1709392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define P12 P11
1710392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define A12 A11
1711392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	IV12[]={0x93,0x13,0x22,0x5d,0xf8,0x84,0x06,0xe5,0x55,0x90,0x9c,0x5a,0xff,0x52,0x69,0xaa,
1712392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x6a,0x7a,0x95,0x38,0x53,0x4f,0x7d,0xa1,0xe4,0xc3,0x03,0xd2,0xa3,0x18,0xa7,0x28,
1713392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xc3,0xc0,0xc9,0x51,0x56,0x80,0x95,0x39,0xfc,0xf0,0xe2,0x42,0x9a,0x6b,0x52,0x54,
1714392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x16,0xae,0xdb,0xf5,0xa0,0xde,0x6a,0x57,0xa6,0x37,0xb3,0x9b},
1715392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C12[]= {0xd2,0x7e,0x88,0x68,0x1c,0xe3,0x24,0x3c,0x48,0x30,0x16,0x5a,0x8f,0xdc,0xf9,0xff,
1716392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x1d,0xe9,0xa1,0xd8,0xe6,0xb4,0x47,0xef,0x6e,0xf7,0xb7,0x98,0x28,0x66,0x6e,0x45,
1717392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x81,0xe7,0x90,0x12,0xaf,0x34,0xdd,0xd9,0xe2,0xf0,0x37,0x58,0x9b,0x29,0x2d,0xb3,
1718392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xe6,0x7c,0x03,0x67,0x45,0xfa,0x22,0xe7,0xe9,0xb7,0x37,0x3b},
1719392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T12[]= {0xdc,0xf5,0x66,0xff,0x29,0x1c,0x25,0xbb,0xb8,0x56,0x8f,0xc3,0xd3,0x76,0xa6,0xd9};
1720392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1721392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 13 */
1722392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	K13[32],
1723392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		*P13=NULL,
1724392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		*A13=NULL,
1725392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		IV13[12],
1726392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		*C13=NULL,
1727392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T13[]={0x53,0x0f,0x8a,0xfb,0xc7,0x45,0x36,0xb9,0xa9,0x63,0xb4,0xf1,0xc4,0xcb,0x73,0x8b};
1728392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1729392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 14 */
1730392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define K14 K13
1731392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define A14 A13
1732392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	P14[16],
1733392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		IV14[12],
1734392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C14[]= {0xce,0xa7,0x40,0x3d,0x4d,0x60,0x6b,0x6e,0x07,0x4e,0xc5,0xd3,0xba,0xf3,0x9d,0x18},
1735392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T14[]= {0xd0,0xd1,0xc8,0xa7,0x99,0x99,0x6b,0xf0,0x26,0x5b,0x98,0xb5,0xd4,0x8a,0xb9,0x19};
1736392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1737392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 15 */
1738392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define A15 A14
1739392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	K15[]= {0xfe,0xff,0xe9,0x92,0x86,0x65,0x73,0x1c,0x6d,0x6a,0x8f,0x94,0x67,0x30,0x83,0x08,
1740392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xfe,0xff,0xe9,0x92,0x86,0x65,0x73,0x1c,0x6d,0x6a,0x8f,0x94,0x67,0x30,0x83,0x08},
1741392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		P15[]= {0xd9,0x31,0x32,0x25,0xf8,0x84,0x06,0xe5,0xa5,0x59,0x09,0xc5,0xaf,0xf5,0x26,0x9a,
1742392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x86,0xa7,0xa9,0x53,0x15,0x34,0xf7,0xda,0x2e,0x4c,0x30,0x3d,0x8a,0x31,0x8a,0x72,
1743392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x1c,0x3c,0x0c,0x95,0x95,0x68,0x09,0x53,0x2f,0xcf,0x0e,0x24,0x49,0xa6,0xb5,0x25,
1744392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xb1,0x6a,0xed,0xf5,0xaa,0x0d,0xe6,0x57,0xba,0x63,0x7b,0x39,0x1a,0xaf,0xd2,0x55},
1745392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		IV15[]={0xca,0xfe,0xba,0xbe,0xfa,0xce,0xdb,0xad,0xde,0xca,0xf8,0x88},
1746392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C15[]= {0x52,0x2d,0xc1,0xf0,0x99,0x56,0x7d,0x07,0xf4,0x7f,0x37,0xa3,0x2a,0x84,0x42,0x7d,
1747392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x64,0x3a,0x8c,0xdc,0xbf,0xe5,0xc0,0xc9,0x75,0x98,0xa2,0xbd,0x25,0x55,0xd1,0xaa,
1748392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x8c,0xb0,0x8e,0x48,0x59,0x0d,0xbb,0x3d,0xa7,0xb0,0x8b,0x10,0x56,0x82,0x88,0x38,
1749392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xc5,0xf6,0x1e,0x63,0x93,0xba,0x7a,0x0a,0xbc,0xc9,0xf6,0x62,0x89,0x80,0x15,0xad},
1750392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T15[]= {0xb0,0x94,0xda,0xc5,0xd9,0x34,0x71,0xbd,0xec,0x1a,0x50,0x22,0x70,0xe3,0xcc,0x6c};
1751392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1752392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 16 */
1753392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define K16 K15
1754392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define IV16 IV15
1755392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	P16[]= {0xd9,0x31,0x32,0x25,0xf8,0x84,0x06,0xe5,0xa5,0x59,0x09,0xc5,0xaf,0xf5,0x26,0x9a,
1756392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x86,0xa7,0xa9,0x53,0x15,0x34,0xf7,0xda,0x2e,0x4c,0x30,0x3d,0x8a,0x31,0x8a,0x72,
1757392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x1c,0x3c,0x0c,0x95,0x95,0x68,0x09,0x53,0x2f,0xcf,0x0e,0x24,0x49,0xa6,0xb5,0x25,
1758392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xb1,0x6a,0xed,0xf5,0xaa,0x0d,0xe6,0x57,0xba,0x63,0x7b,0x39},
1759392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		A16[]= {0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef,0xfe,0xed,0xfa,0xce,0xde,0xad,0xbe,0xef,
1760392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xab,0xad,0xda,0xd2},
1761392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C16[]= {0x52,0x2d,0xc1,0xf0,0x99,0x56,0x7d,0x07,0xf4,0x7f,0x37,0xa3,0x2a,0x84,0x42,0x7d,
1762392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x64,0x3a,0x8c,0xdc,0xbf,0xe5,0xc0,0xc9,0x75,0x98,0xa2,0xbd,0x25,0x55,0xd1,0xaa,
1763392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x8c,0xb0,0x8e,0x48,0x59,0x0d,0xbb,0x3d,0xa7,0xb0,0x8b,0x10,0x56,0x82,0x88,0x38,
1764392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xc5,0xf6,0x1e,0x63,0x93,0xba,0x7a,0x0a,0xbc,0xc9,0xf6,0x62},
1765392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T16[]= {0x76,0xfc,0x6e,0xce,0x0f,0x4e,0x17,0x68,0xcd,0xdf,0x88,0x53,0xbb,0x2d,0x55,0x1b};
1766392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1767392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 17 */
1768392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define K17 K16
1769392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define P17 P16
1770392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define A17 A16
1771392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	IV17[]={0xca,0xfe,0xba,0xbe,0xfa,0xce,0xdb,0xad},
1772392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C17[]= {0xc3,0x76,0x2d,0xf1,0xca,0x78,0x7d,0x32,0xae,0x47,0xc1,0x3b,0xf1,0x98,0x44,0xcb,
1773392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xaf,0x1a,0xe1,0x4d,0x0b,0x97,0x6a,0xfa,0xc5,0x2f,0xf7,0xd7,0x9b,0xba,0x9d,0xe0,
1774392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xfe,0xb5,0x82,0xd3,0x39,0x34,0xa4,0xf0,0x95,0x4c,0xc2,0x36,0x3b,0xc7,0x3f,0x78,
1775392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x62,0xac,0x43,0x0e,0x64,0xab,0xe4,0x99,0xf4,0x7c,0x9b,0x1f},
1776392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T17[]= {0x3a,0x33,0x7d,0xbf,0x46,0xa7,0x92,0xc4,0x5e,0x45,0x49,0x13,0xfe,0x2e,0xa8,0xf2};
1777392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1778392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Test Case 18 */
1779392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define K18 K17
1780392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define P18 P17
1781392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define A18 A17
1782392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromstatic const u8	IV18[]={0x93,0x13,0x22,0x5d,0xf8,0x84,0x06,0xe5,0x55,0x90,0x9c,0x5a,0xff,0x52,0x69,0xaa,
1783392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x6a,0x7a,0x95,0x38,0x53,0x4f,0x7d,0xa1,0xe4,0xc3,0x03,0xd2,0xa3,0x18,0xa7,0x28,
1784392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xc3,0xc0,0xc9,0x51,0x56,0x80,0x95,0x39,0xfc,0xf0,0xe2,0x42,0x9a,0x6b,0x52,0x54,
1785392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x16,0xae,0xdb,0xf5,0xa0,0xde,0x6a,0x57,0xa6,0x37,0xb3,0x9b},
1786392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		C18[]= {0x5a,0x8d,0xef,0x2f,0x0c,0x9e,0x53,0xf1,0xf7,0x5d,0x78,0x53,0x65,0x9e,0x2a,0x20,
1787392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xee,0xb2,0xb2,0x2a,0xaf,0xde,0x64,0x19,0xa0,0x58,0xab,0x4f,0x6f,0x74,0x6b,0xf4,
1788392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0x0f,0xc0,0xc3,0xb7,0x80,0xf2,0x44,0x45,0x2d,0xa3,0xeb,0xf1,0xc5,0xd8,0x2c,0xde,
1789392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			0xa2,0x41,0x89,0x97,0x20,0x0e,0xf8,0x2e,0x44,0xae,0x7e,0x3f},
1790392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		T18[]= {0xa4,0x4a,0x82,0x66,0xee,0x1c,0x8e,0xb0,0xc8,0xb5,0xd4,0xcf,0x5a,0xe9,0xf1,0x9a};
1791392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1792ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root/* Test Case 19 */
1793ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root#define K19 K1
1794ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root#define P19 P1
1795ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root#define IV19 IV1
1796ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root#define C19 C1
1797ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Rootstatic const u8 A19[]= {0xd9,0x31,0x32,0x25,0xf8,0x84,0x06,0xe5,0xa5,0x59,0x09,0xc5,0xaf,0xf5,0x26,0x9a,
1798ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			0x86,0xa7,0xa9,0x53,0x15,0x34,0xf7,0xda,0x2e,0x4c,0x30,0x3d,0x8a,0x31,0x8a,0x72,
1799ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			0x1c,0x3c,0x0c,0x95,0x95,0x68,0x09,0x53,0x2f,0xcf,0x0e,0x24,0x49,0xa6,0xb5,0x25,
1800ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			0xb1,0x6a,0xed,0xf5,0xaa,0x0d,0xe6,0x57,0xba,0x63,0x7b,0x39,0x1a,0xaf,0xd2,0x55,
1801ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			0x52,0x2d,0xc1,0xf0,0x99,0x56,0x7d,0x07,0xf4,0x7f,0x37,0xa3,0x2a,0x84,0x42,0x7d,
1802ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			0x64,0x3a,0x8c,0xdc,0xbf,0xe5,0xc0,0xc9,0x75,0x98,0xa2,0xbd,0x25,0x55,0xd1,0xaa,
1803ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			0x8c,0xb0,0x8e,0x48,0x59,0x0d,0xbb,0x3d,0xa7,0xb0,0x8b,0x10,0x56,0x82,0x88,0x38,
1804ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			0xc5,0xf6,0x1e,0x63,0x93,0xba,0x7a,0x0a,0xbc,0xc9,0xf6,0x62,0x89,0x80,0x15,0xad},
1805ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root		T19[]= {0x5f,0xea,0x79,0x3a,0x2d,0x6f,0x97,0x4d,0x37,0xe6,0x8e,0x0c,0xb8,0xff,0x94,0x92};
1806ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root
1807ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root/* Test Case 20 */
1808ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root#define K20 K1
1809ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root#define A20 A1
1810ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Rootstatic const u8 IV20[64]={0xff,0xff,0xff,0xff},	/* this results in 0xff in counter LSB */
1811ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root		P20[288],
1812ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root		C20[]= {0x56,0xb3,0x37,0x3c,0xa9,0xef,0x6e,0x4a,0x2b,0x64,0xfe,0x1e,0x9a,0x17,0xb6,0x14,
1813ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			0x25,0xf1,0x0d,0x47,0xa7,0x5a,0x5f,0xce,0x13,0xef,0xc6,0xbc,0x78,0x4a,0xf2,0x4f,
1814ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			0x41,0x41,0xbd,0xd4,0x8c,0xf7,0xc7,0x70,0x88,0x7a,0xfd,0x57,0x3c,0xca,0x54,0x18,
1815ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			0xa9,0xae,0xff,0xcd,0x7c,0x5c,0xed,0xdf,0xc6,0xa7,0x83,0x97,0xb9,0xa8,0x5b,0x49,
1816ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			0x9d,0xa5,0x58,0x25,0x72,0x67,0xca,0xab,0x2a,0xd0,0xb2,0x3c,0xa4,0x76,0xa5,0x3c,
1817ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			0xb1,0x7f,0xb4,0x1c,0x4b,0x8b,0x47,0x5c,0xb4,0xf3,0xf7,0x16,0x50,0x94,0xc2,0x29,
1818ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			0xc9,0xe8,0xc4,0xdc,0x0a,0x2a,0x5f,0xf1,0x90,0x3e,0x50,0x15,0x11,0x22,0x13,0x76,
1819ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			0xa1,0xcd,0xb8,0x36,0x4c,0x50,0x61,0xa2,0x0c,0xae,0x74,0xbc,0x4a,0xcd,0x76,0xce,
1820ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			0xb0,0xab,0xc9,0xfd,0x32,0x17,0xef,0x9f,0x8c,0x90,0xbe,0x40,0x2d,0xdf,0x6d,0x86,
1821ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			0x97,0xf4,0xf8,0x80,0xdf,0xf1,0x5b,0xfb,0x7a,0x6b,0x28,0x24,0x1e,0xc8,0xfe,0x18,
1822ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			0x3c,0x2d,0x59,0xe3,0xf9,0xdf,0xff,0x65,0x3c,0x71,0x26,0xf0,0xac,0xb9,0xe6,0x42,
1823ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			0x11,0xf4,0x2b,0xae,0x12,0xaf,0x46,0x2b,0x10,0x70,0xbe,0xf1,0xab,0x5e,0x36,0x06,
1824ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			0x87,0x2c,0xa1,0x0d,0xee,0x15,0xb3,0x24,0x9b,0x1a,0x1b,0x95,0x8f,0x23,0x13,0x4c,
1825ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			0x4b,0xcc,0xb7,0xd0,0x32,0x00,0xbc,0xe4,0x20,0xa2,0xf8,0xeb,0x66,0xdc,0xf3,0x64,
1826ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			0x4d,0x14,0x23,0xc1,0xb5,0x69,0x90,0x03,0xc1,0x3e,0xce,0xf4,0xbf,0x38,0xa3,0xb6,
1827ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			0x0e,0xed,0xc3,0x40,0x33,0xba,0xc1,0x90,0x27,0x83,0xdc,0x6d,0x89,0xe2,0xe7,0x74,
1828ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			0x18,0x8a,0x43,0x9c,0x7e,0xbc,0xc0,0x67,0x2d,0xbd,0xa4,0xdd,0xcf,0xb2,0x79,0x46,
1829ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root			0x13,0xb0,0xbe,0x41,0x31,0x5e,0xf7,0x78,0x70,0x8a,0x70,0xee,0x7d,0x75,0x16,0x5c},
1830ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root		T20[]= {0x8b,0x30,0x7f,0x6b,0x33,0x28,0x6d,0x0a,0xb0,0x26,0xa9,0xed,0x3f,0xe1,0xe8,0x5f};
1831ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root
1832392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#define TEST_CASE(n)	do {					\
1833392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	u8 out[sizeof(P##n)];					\
1834392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	AES_set_encrypt_key(K##n,sizeof(K##n)*8,&key);		\
1835392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	CRYPTO_gcm128_init(&ctx,&key,(block128_f)AES_encrypt);	\
1836392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	CRYPTO_gcm128_setiv(&ctx,IV##n,sizeof(IV##n));		\
1837392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	memset(out,0,sizeof(out));				\
1838392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (A##n) CRYPTO_gcm128_aad(&ctx,A##n,sizeof(A##n));	\
1839392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (P##n) CRYPTO_gcm128_encrypt(&ctx,P##n,out,sizeof(out));	\
1840392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (CRYPTO_gcm128_finish(&ctx,T##n,16) ||		\
1841392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	    (C##n && memcmp(out,C##n,sizeof(out))))		\
1842392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret++, printf ("encrypt test#%d failed.\n",n);	\
1843392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	CRYPTO_gcm128_setiv(&ctx,IV##n,sizeof(IV##n));		\
1844392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	memset(out,0,sizeof(out));				\
1845392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (A##n) CRYPTO_gcm128_aad(&ctx,A##n,sizeof(A##n));	\
1846392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (C##n) CRYPTO_gcm128_decrypt(&ctx,C##n,out,sizeof(out));	\
1847392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (CRYPTO_gcm128_finish(&ctx,T##n,16) ||		\
1848392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	    (P##n && memcmp(out,P##n,sizeof(out))))		\
1849392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ret++, printf ("decrypt test#%d failed.\n",n);	\
1850392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	} while(0)
1851392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1852392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromint main()
1853392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom{
1854392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	GCM128_CONTEXT ctx;
1855392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	AES_KEY key;
1856392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int ret=0;
1857392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1858392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(1);
1859392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(2);
1860392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(3);
1861392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(4);
1862392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(5);
1863392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(6);
1864392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(7);
1865392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(8);
1866392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(9);
1867392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(10);
1868392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(11);
1869392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(12);
1870392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(13);
1871392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(14);
1872392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(15);
1873392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(16);
1874392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(17);
1875392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	TEST_CASE(18);
1876ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root	TEST_CASE(19);
1877ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root	TEST_CASE(20);
1878392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1879392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef OPENSSL_CPUID_OBJ
1880392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
1881392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	size_t start,stop,gcm_t,ctr_t,OPENSSL_rdtsc();
1882392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	union { u64 u; u8 c[1024]; } buf;
1883392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int i;
1884392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1885392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	AES_set_encrypt_key(K1,sizeof(K1)*8,&key);
1886392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	CRYPTO_gcm128_init(&ctx,&key,(block128_f)AES_encrypt);
1887392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	CRYPTO_gcm128_setiv(&ctx,IV1,sizeof(IV1));
1888392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1889392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	CRYPTO_gcm128_encrypt(&ctx,buf.c,buf.c,sizeof(buf));
1890392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	start = OPENSSL_rdtsc();
1891392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	CRYPTO_gcm128_encrypt(&ctx,buf.c,buf.c,sizeof(buf));
1892392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	gcm_t = OPENSSL_rdtsc() - start;
1893392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1894392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	CRYPTO_ctr128_encrypt(buf.c,buf.c,sizeof(buf),
1895392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			&key,ctx.Yi.c,ctx.EKi.c,&ctx.mres,
1896392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(block128_f)AES_encrypt);
1897392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	start = OPENSSL_rdtsc();
1898392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	CRYPTO_ctr128_encrypt(buf.c,buf.c,sizeof(buf),
1899392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			&key,ctx.Yi.c,ctx.EKi.c,&ctx.mres,
1900392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(block128_f)AES_encrypt);
1901392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ctr_t = OPENSSL_rdtsc() - start;
1902392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1903392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	printf("%.2f-%.2f=%.2f\n",
1904392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			gcm_t/(double)sizeof(buf),
1905392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctr_t/(double)sizeof(buf),
1906392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			(gcm_t-ctr_t)/(double)sizeof(buf));
1907392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifdef GHASH
1908ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root	{
1909ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root	void (*gcm_ghash_p)(u64 Xi[2],const u128 Htable[16],
1910ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root				const u8 *inp,size_t len)	= ctx.ghash;
1911ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root
1912ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root	GHASH((&ctx),buf.c,sizeof(buf));
1913392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	start = OPENSSL_rdtsc();
1914ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root	for (i=0;i<100;++i) GHASH((&ctx),buf.c,sizeof(buf));
1915392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	gcm_t = OPENSSL_rdtsc() - start;
1916392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	printf("%.2f\n",gcm_t/(double)sizeof(buf)/(double)i);
1917ff41a4bc41ae1e1391f9b05117623ff70b985983Kenny Root	}
1918392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1919392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
1920392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1921392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
1922392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return ret;
1923392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom}
1924392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
1925