Makefile.in
-aclocal.m4
-configure
-COPYING.LIB
-autom4te.cache
-config
-precomp
-progs/getdate.h
-progs/getdate.y
-symm/modes.am
-symm/stubs.am
+/aclocal.m4
+/configure
+/COPYING.LIB
+/autom4te.cache/
+/config/
+/precomp/
*.sage.py
*.t
*.to
-/symm/safersk.h
-/symm/salsa2012.h
-/symm/salsa208.h
-/symm/salsa20-ietf.h
-/symm/salsa2012-ietf.h
-/symm/salsa208-ietf.h
-/symm/sha224.h
-/symm/sha384.h
-/symm/whirlpool256.h
-/symm/xsalsa20.h
-/symm/xsalsa2012.h
-/symm/xsalsa208.h
-/symm/stubs.gen-stamp
-/symm/t/salsa20
-/symm/xchacha12.h
-/symm/xchacha20.h
-/symm/xchacha8.h
-/symm/chacha12.h
-/symm/chacha20.h
-/symm/chacha8.h
-/symm/chacha12-ietf.h
-/symm/chacha20-ietf.h
-/symm/chacha8-ietf.h
-/symm/xchacha.h
-/symm/kmac128.h
-/symm/kmac256.h
-/symm/safersk.c
-/symm/sha224.c
-/symm/sha3-224.c
-/symm/sha3-224.h
-/symm/sha3-256.c
-/symm/sha3-256.h
-/symm/sha3-384.c
-/symm/sha3-384.h
-/symm/sha3-512.c
-/symm/sha3-512.h
-/symm/sha384.c
-/symm/sha512-224.c
-/symm/sha512-224.h
-/symm/sha512-256.c
-/symm/sha512-256.h
-/symm/shake128.h
-/symm/shake256.h
-/symm/t/sha3
-/symm/whirlpool256.c
-/symm/shake128-xof.h
-/symm/shake256-xof.h
noinst_LTLIBRARIES = libbase.la
libbase_la_SOURCES =
+TEST_LIBS = libbase.la
+
###--------------------------------------------------------------------------
### Component files.
## Clearing secrets from memory.
pkginclude_HEADERS += paranoia.h
+## Reservoir handling.
+pkginclude_HEADERS += rsvr.h
+libbase_la_SOURCES += rsvr.c
+TESTS += rsvr.t$(EXEEXT)
+EXTRA_DIST += t/rsvr
+
## Base definitions for assembler source.
EXTRA_DIST += asm-common.h
+if ASM_DEBUG
+libbase_la_SOURCES += regdump.c regdump.h
+if CPUFAM_X86
+libbase_la_SOURCES += regdump-x86ish.S
+endif
+if CPUFAM_AMD64
+libbase_la_SOURCES += regdump-x86ish.S
+endif
+if CPUFAM_ARMEL
+libbase_la_SOURCES += regdump-arm.S
+endif
+if CPUFAM_ARM64
+libbase_la_SOURCES += regdump-arm64.S
+endif
+endif
+
###----- That's all, folks --------------------------------------------------
/// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
/// MA 02111-1307, USA.
+#ifndef CATACOMB_ASM_COMMON_H
+#define CATACOMB_ASM_COMMON_H
+
///--------------------------------------------------------------------------
/// General definitions.
# define INTADDR__1(addr, got) addr
#endif
-// Permutations for SIMD instructions. SHUF(D, C, B, A) is an immediate,
-// suitable for use in `pshufd' or `shufpd', which copies element D
-// (0 <= D < 4) of the source to element 3 of the destination, element C to
-// element 2, element B to element 1, and element A to element 0.
-#define SHUF(d, c, b, a) (64*(d) + 16*(c) + 4*(b) + (a))
+// Permutations for SIMD instructions. SHUF(A, B, C, D) is an immediate,
+// suitable for use in `pshufd' or `shufpd', which copies element A
+// (0 <= A < 4) of the source to element 0 of the destination, element B to
+// element 1, element C to element 2, and element D to element 3.
+#define SHUF(a, b, c, d) ((a) + 4*(b) + 16*(c) + 64*(d))
// Map register names to their individual pieces.
# define _DECOR_abcd_q(reg) r##reg##x
#endif
-#define _DECOR_xp_b(reg) reg##l
#define _DECOR_xp_w(reg) reg
#define _DECOR_xp_d(reg) e##reg
#if CPUFAM_AMD64
+# define _DECOR_xp_b(reg) reg##l
# define _DECOR_xp_q(reg) r##reg
#endif
# define _DECOR_rn_r(reg) reg
#endif
+#define _DECOR_mem_b(addr) byte ptr addr
+#define _DECOR_mem_w(addr) word ptr addr
+#define _DECOR_mem_d(addr) dword ptr addr
+#if CPUFAM_AMD64
+# define _DECOR_mem_q(addr) qword ptr addr
+#endif
+
+#define _DECOR_imm_b(imm) byte imm
+#define _DECOR_imm_w(imm) word imm
+#define _DECOR_imm_d(imm) dword imm
+#if CPUFAM_AMD64
+# define _DECOR_imm_q(imm) qword imm
+#endif
+
#if CPUFAM_X86
# define _DECOR_abcd_r(reg) e##reg##x
# define _DECOR_xp_r(reg) e##reg
# define _DECOR_ip_r(reg) e##reg
+# define _DECOR_mem_r(addr) dword ptr addr
+# define _DECOR_imm_r(imm) dword imm
#endif
#if CPUFAM_AMD64
# define _DECOR_abcd_r(reg) r##reg##x
# define _DECOR_xp_r(reg) r##reg
# define _DECOR_ip_r(reg) r##reg
-#endif
-
-#define _DECOR_mem_b(addr) byte ptr addr
-#define _DECOR_mem_w(addr) word ptr addr
-#define _DECOR_mem_d(addr) dword ptr addr
-#if CPUFAM_AMD64
-# define _DECOR_mem_q(addr) qword ptr addr
+# define _DECOR_mem_r(addr) qword ptr addr
+# define _DECOR_imm_r(imm) qword imm
#endif
// R_r(decor) applies decoration decor to register r, which is an internal
// address addr (which should supply its own square-brackets).
#define MEM(decor, addr) _DECOR(mem, decor, addr)
+// Refer to an immediate datum of the type implied by decor.
+#define IMM(decor, imm) _DECOR(mem, decor, imm)
+
// Applies decoration decor to assembler-level register name reg.
#define _REGFORM(reg, decor) _GLUE(_REGFORM_, reg)(decor)
#define WHOLE(reg) _REGFORM(reg, r)
// Stack management and unwinding.
-.macro setfp fp, offset = 0
+.macro setfp fp=R_bp(r), offset=0
.if \offset == 0
mov \fp, R_sp(r)
#if __ELF__
.macro dropfp; _dropfp \fp, \offset; .endm
.endm
-.macro _dropfp fp, offset = 0
+.macro _dropfp fp, offset=0
.if \offset == 0
mov R_sp(r), \fp
#if __ELF__
#endif
-#if CPUFAM_X86
-
-.macro _reg.0
- // Stash GP registers and establish temporary stack frame.
- pushfd
- push eax
- push ecx
- push edx
- push ebp
- mov ebp, esp
- and esp, ~15
- sub esp, 512
- fxsave [esp]
-.endm
-
-.macro _reg.1
-.endm
-
-.macro _reg.2
-.endm
-
-.macro _reg.3 fmt
- // Print FMT and the other established arguments.
- lea eax, .L$_reg$msg.\@
- push eax
- call printf
- jmp .L$_reg$cont.\@
-.L$_reg$msg.\@:
- .ascii ";; \fmt\n\0"
-.L$_reg$cont.\@:
- mov eax, ebp
- and eax, ~15
- sub eax, 512
- fxrstor [eax]
- mov esp, ebp
- pop ebp
- pop edx
- pop ecx
- pop eax
- popfd
-.endm
-
-.macro msg msg
- _reg.0
- _reg.1
- _reg.2
- _reg.3 "\msg"
-.endm
-
-.macro reg r, msg
- _reg.0
- .ifeqs "\r", "esp"
- lea eax, [ebp + 20]
- push eax
- .else
- .ifeqs "\r", "ebp"
- push [ebp]
- .else
- push \r
- .endif
- .endif
- _reg.1
- _reg.2
- _reg.3 "\msg: \r = %08x"
-.endm
-
-.macro xmmreg r, msg
- _reg.0
- _reg.1
- _reg.2
- movdqu xmm0, \r
- pshufd xmm0, xmm0, 0x1b
- sub esp, 16
- movdqa [esp], xmm0
- _reg.3 "\msg: \r = %08x %08x %08x %08x"
-.endm
-
-.macro mmreg r, msg
- _reg.0
- _reg.1
- _reg.2
- pshufw \r, \r, 0x4e
- sub esp, 8
- movq [esp], \r
- _reg.3 "\msg: \r = %08x %08x"
-.endm
-
-.macro freg i, msg
- _reg.0
- _reg.1
- _reg.2
- finit
- fldt [esp + 32 + 16*\i]
- sub esp, 12
- fstpt [esp]
- _reg.3 "\msg: st(\i) = %.20Lg"
-.endm
-
-.macro fxreg i, msg
- _reg.0
- _reg.1
- _reg.2
- finit
- fldt [esp + 32 + 16*\i]
- sub esp, 12
- fstpt [esp]
- _reg.3 "\msg: st(\i) = %La"
-.endm
-
-#endif
-
///--------------------------------------------------------------------------
/// ARM-specific hacking.
#if WANT_PIC
ldr\cond \reg, .L$_leaextq$\@
.L$_leaextq_pc$\@:
- .if .L$_pcoff == 8
+ .if .L$_pcoff == 8
ldr\cond \reg, [pc, \reg]
- .else
+ .else
add\cond \reg, pc
ldr\cond \reg, [\reg]
- .endif
+ .endif
_LIT
.balign 4
.L$_leaextq$\@:
#endif
.endm
+.macro vzero vz=q15
+ // Set VZ (default q15) to zero.
+ vmov.u32 \vz, #0
+.endm
+
+.macro vshl128 vd, vn, nbit, vz=q15
+ // Set VD to VN shifted left by NBIT. Assume VZ (default q15) is
+ // all-bits-zero. NBIT must be a multiple of 8.
+ .if \nbit&3 != 0
+ .error "shift quantity must be whole number of bytes"
+ .endif
+ vext.8 \vd, \vz, \vn, #16 - (\nbit >> 3)
+.endm
+
+.macro vshr128 vd, vn, nbit, vz=q15
+ // Set VD to VN shifted right by NBIT. Assume VZ (default q15) is
+ // all-bits-zero. NBIT must be a multiple of 8.
+ .if \nbit&3 != 0
+ .error "shift quantity must be whole number of bytes"
+ .endif
+ vext.8 \vd, \vn, \vz, #\nbit >> 3
+.endm
+
// Apply decoration decor to register name reg.
#define _REGFORM(reg, decor) _GLUE(_REGFORM_, reg)(decor)
#define QQ(qlo, qhi) D0(qlo)-D1(qhi)
// Stack management and unwinding.
-.macro setfp fp, offset = 0
+.macro setfp fp=r11, offset=0
.if \offset == 0
mov \fp, sp
.setfp \fp, sp
.L$_frameptr_p = -1
.endm
-.macro _dropfp fp, offset = 0
+.macro _dropfp fp, offset=0
.if \offset == 0
mov sp, \fp
.else
.endm
.macro pushreg rr:vararg
- stmfd sp!, {\rr}
+ push {\rr}
.save {\rr}
.endm
.macro popreg rr:vararg
- ldmfd sp!, {\rr}
+ pop {\rr}
.endm
.macro pushvfp rr:vararg
#endif
.endm
+.macro vzero vz=v31
+ // Set VZ (default v31) to zero.
+ dup \vz\().4s, wzr
+.endm
+
+.macro vshl128 vd, vn, nbit, vz=v31
+ // Set VD to VN shifted left by NBIT. Assume VZ (default v31) is
+ // all-bits-zero. NBIT must be a multiple of 8.
+ .if \nbit&3 != 0
+ .error "shift quantity must be whole number of bytes"
+ .endif
+ ext \vd\().16b, \vz\().16b, \vn\().16b, #16 - (\nbit >> 3)
+.endm
+
+.macro vshr128 vd, vn, nbit, vz=v31
+ // Set VD to VN shifted right by NBIT. Assume VZ (default v31) is
+ // all-bits-zero. NBIT must be a multiple of 8.
+ .if \nbit&3 != 0
+ .error "shift quantity must be whole number of bytes"
+ .endif
+ ext \vd\().16b, \vn\().16b, \vz\().16b, #\nbit >> 3
+.endm
+
// Stack management and unwinding.
-.macro setfp fp, offset = 0
+.macro setfp fp=x29, offset=0
// If you're just going through the motions with a fixed-size stack frame,
// then you want to say `add x29, sp, #OFFSET' directly, which will avoid
// pointlessly restoring sp later.
.L$_frameptr_p = -1
.endm
-.macro _dropfp fp, offset = 0
+.macro _dropfp fp, offset=0
.if \offset == 0
mov sp, \fp
.cfi_def_cfa_register sp
.cfi_adjust_cfa_offset -\n
.endm
-.macro pushreg x, y=
- .ifeqs "\y", ""
+.macro pushreg x, y=nil
+ .ifeqs "\y", "nil"
str \x, [sp, #-16]!
.cfi_adjust_cfa_offset +16
.cfi_rel_offset \x, 0
.endif
.endm
-.macro popreg x, y=
- .ifeqs "\y", ""
+.macro popreg x, y=nil
+ .ifeqs "\y", "nil"
ldr \x, [sp], #16
.cfi_restore \x
.cfi_adjust_cfa_offset -16
.endif
.endm
-.macro savereg x, y, z=
- .ifeqs "\z", ""
- str \x, [sp, #\y]
+.macro savereg x, y, z=nil
+ .ifeqs "\z", "nil"
+ str \x, [sp, \y]
.cfi_rel_offset \x, \y
.else
stp \x, \y, [sp, #\z]
.endif
.endm
-.macro rstrreg x, y, z=
- .ifeqs "\z", ""
- ldr \x, [sp, #\y]
+.macro rstrreg x, y, z=nil
+ .ifeqs "\z", "nil"
+ ldr \x, [sp, \y]
.cfi_restore \x
.else
ldp \x, \y, [sp, #\z]
#endif
#ifndef F
-# define F(name) name
+# ifdef SYM_USCORE
+# define F(name) _##name
+# else
+# define F(name) name
+# endif
#endif
#ifndef TYPE_FUNC
#endif
///----- That's all, folks --------------------------------------------------
+
+#endif
# define EFLAGS_ID (1u << 21)
# define CPUID1D_SSE2 (1u << 26)
# define CPUID1D_FXSR (1u << 24)
+# define CPUID1C_PCLMUL (1u << 1)
+# define CPUID1C_SSSE3 (1u << 9)
# define CPUID1C_AESNI (1u << 25)
+# define CPUID1C_AVX (1u << 28)
# define CPUID1C_RDRAND (1u << 30)
struct cpuid { unsigned a, b, c, d; };
_(ARM_NEON, "arm:neon") \
_(ARM_V4, "arm:v4") \
_(ARM_D32, "arm:d32") \
- _(ARM_AES, "arm:aes")
+ _(ARM_AES, "arm:aes") \
+ _(ARM_PMULL, "arm:pmull")
#endif
#if CPUFAM_ARM64
# define WANTAUX(_) \
WANT_AT_HWCAP(_)
# define CAPMAP(_) \
_(ARM_NEON, "arm:neon") \
- _(ARM_AES, "arm:aes")
+ _(ARM_AES, "arm:aes") \
+ _(ARM_PMULL, "arm:pmull")
#endif
/* Build the bitmask for `hwcaps' from the `CAPMAP' list. */
# ifdef HWCAP2_AES
if (probed.hwcap2 & HWCAP2_AES) hw |= HF_ARM_AES;
# endif
+# ifdef HWCAP2_PMULL
+ if (probed.hwcap2 & HWCAP2_PMULL) hw |= HF_ARM_PMULL;
+# endif
#endif
#if CPUFAM_ARM64
if (probed.hwcap & HWCAP_ASIMD) hw |= HF_ARM_NEON;
if (probed.hwcap & HWCAP_AES) hw |= HF_ARM_AES;
+ if (probed.hwcap & HWCAP_PMULL) hw |= HF_ARM_PMULL;
#endif
/* Store the bitmask of features we probed for everyone to see. */
xmm_registers_available_p());
CASE_CPUFEAT(X86_RDRAND, "x86:rdrand",
cpuid_features_p(0, CPUID1C_RDRAND) && rdrand_works_p());
+ CASE_CPUFEAT(X86_AVX, "x86:avx",
+ cpuid_features_p(0, CPUID1C_AVX) &&
+ xmm_registers_available_p());
+ CASE_CPUFEAT(X86_SSSE3, "x86:ssse3",
+ cpuid_features_p(0, CPUID1C_SSSE3) &&
+ xmm_registers_available_p());
+ CASE_CPUFEAT(X86_PCLMUL, "x86:pclmul",
+ cpuid_features_p(0, CPUID1C_PCLMUL) &&
+ xmm_registers_available_p());
#endif
#ifdef CAPMAP
# define FEATP__CASE(feat, tok) \
CPUFEAT_ARM_V4, /* VFPv4 and/or SIMD v2 */
CPUFEAT_ARM_D32, /* 32 double registers, not 16 */
CPUFEAT_X86_RDRAND, /* Built-in entropy source */
- CPUFEAT_ARM_AES /* AES instructions */
+ CPUFEAT_ARM_AES, /* AES instructions */
+ CPUFEAT_X86_AVX, /* AVX 1 (i.e., 256-bit YMM regs) */
+ CPUFEAT_X86_SSSE3, /* Supplementary SSE 3 */
+ CPUFEAT_X86_PCLMUL, /* Carry-less multiplication */
+ CPUFEAT_ARM_PMULL /* Polynomial multiplication */
};
extern int cpu_feature_p(int /*feat*/);
return (0);
}
+/* --- @keysz_pad@ --- *
+ *
+ * Arguments: @size_t sz@ = a proposed key size
+ * @const octet *ksz@ = pointer to key size table
+ *
+ * Returns: A key size, at least as large as @sz@, or zero if no such
+ * size is available.
+ */
+
+size_t keysz_pad(size_t sz, const octet *ksz)
+{
+ unsigned op = ksz[0]&KSZ_OPMASK;
+ unsigned wd = (ksz[0]&KSZ_16BIT) ? 2 : 1;
+ unsigned t, u, v;
+
+ ksz++;
+#define ARG(i) (wd == 1 ? ksz[i] : LOAD16(ksz + 2*i))
+ switch (op) {
+ case KSZ_ANY: return (sz);
+ case KSZ_RANGE:
+ t = ARG(1); u = ARG(2); v = ARG(3);
+ if (v) { sz += v - 1; sz -= sz%v; }
+ if (u && sz > u) return (0);
+ if (sz < t) return (t);
+ return (sz);
+ case KSZ_SET:
+ u = 0;
+ for (;;) {
+ t = ARG(0); ksz += wd; if (!t) break;
+ if (sz <= t && (!u || u > t)) u = t;
+ }
+ return (u);
+ }
+#undef ARG
+
+ assert(((void)"bad key size table", 0));
+ return (0);
+}
+
/*----- That's all, folks -------------------------------------------------*/
#define KSZ_ASSERT(pre, sz) \
assert(((void)"Bad key size for " #pre, KSZ_CHECK(pre, sz)))
+/* --- @keysz_pad@ --- *
+ *
+ * Arguments: @size_t sz@ = a proposed key size
+ * @const octet *ksz@ = pointer to key size table
+ *
+ * Returns: A key size, at least as large as @sz@, or zero if no such
+ * size is available.
+ */
+
+extern size_t keysz_pad(size_t /*sz*/, const octet */*ksz*/);
+
/*----- Key size conversions ----------------------------------------------*/
/* --- @keysz_fromdl@, @_fromschnorr@, @_fromif@, @_fromec@ --- *
--- /dev/null
+/// -*- mode: asm; asm-comment-char: ?/ -*-
+///
+/// Register dump and debugging for 32-bit ARM
+///
+/// (c) 2019 Straylight/Edgeware
+///
+
+///----- Licensing notice ---------------------------------------------------
+///
+/// This file is part of Catacomb.
+///
+/// Catacomb is free software: you can redistribute it and/or modify it
+/// under the terms of the GNU Library General Public License as published
+/// by the Free Software Foundation; either version 2 of the License, or
+/// (at your option) any later version.
+///
+/// Catacomb is distributed in the hope that it will be useful, but
+/// WITHOUT ANY WARRANTY; without even the implied warranty of
+/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+/// Library General Public License for more details.
+///
+/// You should have received a copy of the GNU Library General Public
+/// License along with Catacomb. If not, write to the Free Software
+/// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+/// USA.
+
+///--------------------------------------------------------------------------
+/// Preliminaries.
+
+#include "config.h"
+#include "asm-common.h"
+#include "regdump.h"
+
+ .arch armv7-a
+ .fpu neon
+
+ .text
+
+///--------------------------------------------------------------------------
+/// Main code.
+
+FUNC(regdump_gpsave)
+ endprologue
+ // On entry, r13 should point to `REGDUMP_GPSIZE' bytes of
+ // word-aligned storage to be the general-purpose save area, with r12
+ // and r14 already saved. On exit, the initial registers are saved
+ // in this space, and modified: r4 points to the general-purpose save
+ // area, r6 holds the focus address (possibly already saved), r0
+ // contains the number of bytes required in the extended save area,
+ // and other general-purpose registers are clobbered or used to
+ // communicate with `regdump_xtsave' below. Doing anything other
+ // than lowering the stack pointer and calling `regdump_xtsave' is
+ // not recommended.
+
+ // Save the easy registers.
+ stmia r13, {r0-r11}
+ mov r4, r13
+
+ // Determine the previous stack pointer and save it.
+ add r0, r4, #REGDUMP_GPSIZE
+ str r0, [r4, #13*4]
+
+ // Capture the status flags and return address. If the return
+ // address has its low bit set, then the caller was in Thumb state:
+ // clear the bit from the reconstructed PC, and set the corresponding
+ // CPSR bit.
+ mrs r0, cpsr
+ tst r14, #1
+ bic r1, r14, #1
+ orrne r0, r0, #0x00000020
+ str r0, [r13, #4*REGIX_CPSR]
+ str r1, [r13, #15*4]
+
+ // Load the focus address and save it as r6.
+ ldr r6, [r4, #4*REGIX_ADDR]
+
+ // Determine the extended save area size.
+ ldgot
+ mov r0, #8 + 8
+ leaext r12, regdump__flags
+ ldr r12, [r12]
+ tst r12, #REGF_VFP
+ addne r0, r0, #REGDUMP_FPSIZE_D16
+ tstne r12, #REGF_D32
+ addne r0, r0, #REGDUMP_FPSIZE_D32 - REGDUMP_FPSIZE_D16
+
+ // Done.
+ bx r14
+
+ENDFUNC
+
+FUNC(regdump_gprstr)
+ endprologue
+ // On entry, r4 points to a general-purpose save area, established by
+ // `regdump_gpsave'. On exit, the general-purpose registers (other
+ // than r13 and r14) are restored to their original values.
+
+ // Restore the processor flags.
+ ldr r0, [r4, #4*REGIX_CPSR]
+ msr cpsr_fs, r0
+
+ // Load the easy registers.
+ ldmia r4, {r0-r12}
+
+ // Done.
+ bx r14
+
+ENDFUNC
+
+FUNC(regdump_xtsave)
+ endprologue
+ // On entry, r13 points to an extended save area, of size determined
+ // by `regdump_gpsave' above. On exit, the save area is filled in
+ // and a handy map placed at its base.
+
+ // Set up the map/extended save area pointer.
+ add r5, r13, #7
+ bic r5, r5, #7
+
+ // Start by filling in the easy part of the map.
+ str r4, [r5, #regmap_gp]
+
+ // Fetch the flags explaining what to do.
+ ldgot
+ leaext r12, regdump__flags
+ ldr r12, [r12]
+
+ // Figure out whether there are VFP/NEON registers.
+ tst r12, #REGF_VFP
+ moveq r3, #0
+ addne r3, r5, #regmap_size
+ str r3, [r5, #regmap_fp]
+ beq 9f
+
+ // Get the FP status register.
+ vmrs r0, fpscr
+ str r0, [r3], #8
+
+ // At least the first 16.
+ vstmia r3!, {d0-d15}
+
+ // Maybe the other 16 too.
+ tst r12, #REGF_D32
+ vstmiane r3!, {d16-d31}
+
+ // Done.
+9: bx r14
+
+ENDFUNC
+
+FUNC(regdump_xtrstr)
+ endprologue
+ // On entry, r5 points to a register-save map. On exit, the extended
+ // registers are restored from the save area, r4 (pointing to the
+ // general-purpose save area) is preserved, and the other general
+ // registers are clobbered.
+
+ // Fetch the flags explaining what to do.
+ ldgot
+ leaext r12, regdump__flags
+ ldr r12, [r12]
+
+ // Figure out if there are VFP/NEON registers.
+ tst r12, #REGF_VFP
+ beq 9f
+ ldr r3, [r5, #regmap_fp]
+
+ // Load the FP status register.
+ ldr r0, [r3], #8
+ vmsr fpscr, r0
+
+ // Load the first 16 registers.
+ vldmia r3!, {d0-d15}
+
+ // And maybe the other 16.
+ tst r12, #REGF_D32
+ vldmiane r3!, {d16-d31}
+
+ // Done.
+9: bx r14
+
+ENDFUNC
+
+///----- That's all, folks --------------------------------------------------
--- /dev/null
+/// -*- mode: asm; asm-comment-char: ?/ -*-
+///
+/// Register dump and debugging for 64-bit ARM
+///
+/// (c) 2019 Straylight/Edgeware
+///
+
+///----- Licensing notice ---------------------------------------------------
+///
+/// This file is part of Catacomb.
+///
+/// Catacomb is free software: you can redistribute it and/or modify it
+/// under the terms of the GNU Library General Public License as published
+/// by the Free Software Foundation; either version 2 of the License, or
+/// (at your option) any later version.
+///
+/// Catacomb is distributed in the hope that it will be useful, but
+/// WITHOUT ANY WARRANTY; without even the implied warranty of
+/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+/// Library General Public License for more details.
+///
+/// You should have received a copy of the GNU Library General Public
+/// License along with Catacomb. If not, write to the Free Software
+/// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+/// USA.
+
+///--------------------------------------------------------------------------
+/// Preliminaries.
+
+#include "config.h"
+#include "asm-common.h"
+#include "regdump.h"
+
+ .arch armv8-a
+
+ .text
+
+///--------------------------------------------------------------------------
+/// Main code.
+
+FUNC(regdump_gpsave)
+ endprologue
+ // On entry, sp should point to `REGDUMP_GPSIZE' bytes of
+ // doubleword-aligned storage to be the general-purpose save area,
+ // with x16, x17, and x30 already saved. On exit, the initial
+ // registers are saved in this space, and modified: x20 points to the
+ // general-purpose save area, x22 holds the focus address (possibly
+ // already saved), x0 contains the number of bytes required in the
+ // extended save area, and other general-purpose registers are
+ // clobbered or used to communicate with `regdump_xtsave' below.
+ // Doing anything other than lowering the stack pointer and calling
+ // `regdump_xtsave' is not recommended.
+
+ // Save the easy registers.
+ stp x0, x1, [sp, #0]
+ stp x2, x3, [sp, #16]
+ stp x4, x5, [sp, #32]
+ stp x6, x7, [sp, #48]
+ stp x8, x9, [sp, #64]
+ stp x10, x11, [sp, #80]
+ stp x12, x13, [sp, #96]
+ stp x14, x15, [sp, #112]
+ stp x18, x19, [sp, #144]
+ stp x20, x21, [sp, #160]
+ stp x22, x23, [sp, #176]
+ stp x24, x25, [sp, #192]
+ stp x26, x27, [sp, #208]
+ stp x28, x29, [sp, #224]
+
+ mov x20, sp
+
+ // Determine the previous stack pointer and save it.
+ add x0, x20, #REGDUMP_GPSIZE
+ str x0, [x20, #31*8]
+
+ // Capture the status flags.
+ mrs x0, nzcv
+ str x0, [x20, #8*REGIX_NZCV]
+
+ // Set the return address as our PC.
+ str x30, [x20, #8*REGIX_PC]
+
+ // Load the focus address and save it as x22.
+ ldr x22, [x20, #8*REGIX_ADDR]
+
+ // Determine the extended save area size.
+ mov x0, #REGDUMP_FPSIZE
+
+ // Done.
+ ret
+
+ENDFUNC
+
+FUNC(regdump_gprstr)
+ endprologue
+ // On entry, x20 points to a general-purpose save area, established
+ // by `regdump_gpsave'. On exit, the general-purpose registers
+ // (other than x30 and sp) are restored to their original values.
+
+ // Restore the processor flags.
+ ldr w0, [x20, #8*REGIX_NZCV]
+ msr nzcv, x0
+
+ // Load the easy registers.
+ ldp x0, x1, [sp, #0]
+ ldp x2, x3, [sp, #16]
+ ldp x4, x5, [sp, #32]
+ ldp x6, x7, [sp, #48]
+ ldp x8, x9, [sp, #64]
+ ldp x10, x11, [sp, #80]
+ ldp x12, x13, [sp, #96]
+ ldp x14, x15, [sp, #112]
+ ldp x16, x17, [sp, #128]
+ ldp x18, x19, [sp, #144]
+ ldp x20, x21, [sp, #160]
+ ldp x22, x23, [sp, #176]
+ ldp x24, x25, [sp, #192]
+ ldp x26, x27, [sp, #208]
+ ldp x28, x29, [sp, #224]
+
+ // Done.
+ ret
+
+ENDFUNC
+
+FUNC(regdump_xtsave)
+ endprologue
+ // On entry, sp points to an extended save area, of size determined
+ // by `regdump_gpsave' above. On exit, the save area is filled in
+ // and a handy map placed at its base.
+
+ // Set up the map/extended save area pointer.
+ mov x21, sp
+
+ // Start by filling in the easy part of the map.
+ add x0, x21, #regmap_size
+ stp x20, x0, [x21]
+
+ // Get the FP status register.
+ mrs x1, fpsr
+ mrs x2, fpcr
+ stp w1, w2, [x0], #8
+
+ // Store the SIMD registers.
+ stp q0, q1, [x0, #0]
+ stp q2, q3, [x0, #32]
+ stp q4, q5, [x0, #64]
+ stp q6, q7, [x0, #96]
+ stp q8, q9, [x0, #128]
+ stp q10, q11, [x0, #160]
+ stp q12, q13, [x0, #192]
+ stp q14, q15, [x0, #224]
+ stp q16, q17, [x0, #256]
+ stp q18, q19, [x0, #288]
+ stp q20, q21, [x0, #320]
+ stp q22, q23, [x0, #352]
+ stp q24, q25, [x0, #384]
+ stp q26, q27, [x0, #416]
+ stp q28, q29, [x0, #448]
+ stp q30, q31, [x0, #480]
+
+ // Done.
+ ret
+
+ENDFUNC
+
+FUNC(regdump_xtrstr)
+ endprologue
+ // On entry, x21 points to a register-save map. On exit, the
+ // extended registers are restored from the save area, x20 (pointing
+ // to the general-purpose save area) is preserved, and the other
+ // general registers are clobbered.
+
+ ldr x0, [x21, #regmap_fp]
+
+ // Load the FP status and control registers.
+ ldp w1, w2, [x0], #8
+ msr fpsr, x1
+ msr fpcr, x2
+
+ // Load the SIMD registers.
+ ldp q0, q1, [x0, #0]
+ ldp q2, q3, [x0, #32]
+ ldp q4, q5, [x0, #64]
+ ldp q6, q7, [x0, #96]
+ ldp q8, q9, [x0, #128]
+ ldp q10, q11, [x0, #160]
+ ldp q12, q13, [x0, #192]
+ ldp q14, q15, [x0, #224]
+ ldp q16, q17, [x0, #256]
+ ldp q18, q19, [x0, #288]
+ ldp q20, q21, [x0, #320]
+ ldp q22, q23, [x0, #352]
+ ldp q24, q25, [x0, #384]
+ ldp q26, q27, [x0, #416]
+ ldp q28, q29, [x0, #448]
+ ldp q30, q31, [x0, #480]
+
+ // Done.
+ ret
+
+ENDFUNC
+
+///----- That's all, folks --------------------------------------------------
--- /dev/null
+/// -*- mode: asm; asm-comment-char: ?/ -*-
+///
+/// Register dump and debugging for x86
+///
+/// (c) 2019 Straylight/Edgeware
+///
+
+///----- Licensing notice ---------------------------------------------------
+///
+/// This file is part of Catacomb.
+///
+/// Catacomb is free software: you can redistribute it and/or modify it
+/// under the terms of the GNU Library General Public License as published
+/// by the Free Software Foundation; either version 2 of the License, or
+/// (at your option) any later version.
+///
+/// Catacomb is distributed in the hope that it will be useful, but
+/// WITHOUT ANY WARRANTY; without even the implied warranty of
+/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+/// Library General Public License for more details.
+///
+/// You should have received a copy of the GNU Library General Public
+/// License along with Catacomb. If not, write to the Free Software
+/// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+/// USA.
+
+///--------------------------------------------------------------------------
+/// Preliminaries.
+
+#include "config.h"
+#include "asm-common.h"
+#include "regdump.h"
+
+ .text
+ .arch pentium4
+ .arch .xsave
+
+///--------------------------------------------------------------------------
+/// Main code.
+
+FUNC(regdump_gpsave)
+ endprologue
+ // On entry, r/esp should point to a return address and
+ // `REGDUMP_GPSIZE' bytes of word-aligned storage to be the
+ // general-purpose save area, with flags saved in the bottom word,
+ // r/eax saved in the fourth, and (on 32-bit x86) ebx in the fifth.
+ // On exit, the initial registers are saved in this space, and
+ // modified: r/ebp points to the general-purpose save area, ecx
+ // contains the number of bytes required in the extended save area,
+ // ebx is preserved on 32-bit x86, and other general-purpose
+ // registers are clobbered or used to communicate with
+ // `regdump_xtsave' below. Doing anything other than lowering the
+ // stack pointer and calling `regdump_xtsave' is not recommended.
+
+ // Other code will insist that df is clear.
+ cld
+
+ // Save r/ebp and establish it pointing to the save area.
+ mov [R_sp(r) + WORDSZ + REGIX_BP*WORDSZ], R_bp(r)
+ lea R_bp(r), [R_sp(r) + WORDSZ]
+
+ // Save the other easy general-purpose registers.
+#if !CPUFAM_X86
+ mov [R_bp(r) + REGIX_BX*WORDSZ], R_b(r)
+#endif
+ mov [R_bp(r) + REGIX_CX*WORDSZ], R_c(r)
+ mov [R_bp(r) + REGIX_DX*WORDSZ], R_d(r)
+ mov [R_bp(r) + REGIX_SI*WORDSZ], R_si(r)
+ mov [R_bp(r) + REGIX_DI*WORDSZ], R_di(r)
+#if CPUFAM_AMD64
+ mov [R_bp(r) + REGIX_R8*WORDSZ], R_r8(r)
+ mov [R_bp(r) + REGIX_R9*WORDSZ], R_r9(r)
+ mov [R_bp(r) + REGIX_R10*WORDSZ], R_r10(r)
+ mov [R_bp(r) + REGIX_R11*WORDSZ], R_r11(r)
+ mov [R_bp(r) + REGIX_R12*WORDSZ], R_r12(r)
+ mov [R_bp(r) + REGIX_R13*WORDSZ], R_r13(r)
+ mov [R_bp(r) + REGIX_R14*WORDSZ], R_r14(r)
+ mov [R_bp(r) + REGIX_R15*WORDSZ], R_r15(r)
+#endif
+
+ // Determine the previous stack pointer and save it.
+#if CPUFAM_AMD64 && ABI_SYSV
+ lea R_a(r), [R_bp(r) + 128 + REGDUMP_GPSIZE]
+#else
+ lea R_a(r), [R_bp(r) + REGDUMP_GPSIZE]
+#endif
+ mov [R_bp(r) + REGIX_SP*WORDSZ], R_a(r)
+
+ // Collect the return address and save it as r/eip.
+ mov R_a(r), [R_sp(r)]
+ mov [R_bp(r) + REGIX_IP*WORDSZ], R_a(r)
+
+ // Save the segment registers.
+ lea R_a(r), [R_bp(r) + REGIX_GPLIM*WORDSZ]
+ mov [R_a(r) + 2*REGIX_CS], cs
+ mov [R_a(r) + 2*REGIX_DS], ds
+ mov [R_a(r) + 2*REGIX_SS], ss
+ mov [R_a(r) + 2*REGIX_ES], es
+ mov [R_a(r) + 2*REGIX_FS], fs
+ mov [R_a(r) + 2*REGIX_GS], gs
+
+ // Determine the extended save area size. Preserve ebx on 32-bit x86
+ // here, because the caller needs it for PLT-indirect calls.
+#if CPUFAM_X86
+ push ebx
+#endif
+ mov eax, 0x01
+ cpuid
+ test ecx, 1 << 26
+ je 1f
+
+ mov eax, 0x0d
+ mov ecx, 0x00
+ cpuid
+ add ecx, regmap_size + 64 // map + align
+ jmp 8f
+
+1: mov ecx, 512 + regmap_size + 16 // fxsave + map + align
+
+ // Done.
+8:
+#if CPUFAM_X86
+ pop ebx
+#endif
+ ret
+
+ENDFUNC
+
+FUNC(regdump_gprstr)
+ endprologue
+ // On entry, r/ebp points to a general-purpose save area, established
+ // by `regdump_gpsave'. On exit, the general-purpose registers
+ // (other than the stack pointer) are restored to their original
+ // values.
+
+ // We assume nobody actually fiddled with the segment registers. So
+ // just the actual integer registers to do.
+ mov R_a(r), [R_bp(r) + REGIX_AX*WORDSZ]
+ mov R_b(r), [R_bp(r) + REGIX_BX*WORDSZ]
+ mov R_c(r), [R_bp(r) + REGIX_CX*WORDSZ]
+ mov R_d(r), [R_bp(r) + REGIX_DX*WORDSZ]
+ mov R_si(r), [R_bp(r) + REGIX_SI*WORDSZ]
+ mov R_di(r), [R_bp(r) + REGIX_DI*WORDSZ]
+#if CPUFAM_AMD64
+ mov R_r8(r), [R_bp(r) + REGIX_R8*WORDSZ]
+ mov R_r9(r), [R_bp(r) + REGIX_R9*WORDSZ]
+ mov R_r10(r), [R_bp(r) + REGIX_R10*WORDSZ]
+ mov R_r11(r), [R_bp(r) + REGIX_R11*WORDSZ]
+ mov R_r12(r), [R_bp(r) + REGIX_R12*WORDSZ]
+ mov R_r13(r), [R_bp(r) + REGIX_R13*WORDSZ]
+ mov R_r14(r), [R_bp(r) + REGIX_R14*WORDSZ]
+ mov R_r15(r), [R_bp(r) + REGIX_R15*WORDSZ]
+#endif
+ mov R_bp(r), [R_bp(r) + REGIX_BP*WORDSZ]
+
+ // Done.
+ ret
+
+ENDFUNC
+
+#ifdef CPUFAM_AMD64
+# define fxsave fxsave64
+# define fxrstor fxrstor64
+# define xsave xsave64
+# define xrstor xrstor64
+#endif
+
+FUNC(regdump_xtsave)
+ endprologue
+ // On entry, r/esp points to a return address and extended save area,
+ // of size determined by `regdump_gpsave' above. On exit, the save
+ // area is filled in and a handy map placed at its base, the x87
+ // floating-point state is reset, r/ebp is left pointing to the
+ // register map, ebx is preserved on 32-bit x86, and the other
+ // general registers are clobbered.
+
+ // Start by filling in the easy parts of the map.
+ mov [R_sp(r) + WORDSZ + regmap_gp], R_bp(r)
+ lea R_bp(r), [R_sp(r) + WORDSZ]
+
+ xor eax, eax // clears rax too on amd64
+ mov [R_bp(r) + regmap_avx], R_a(r)
+
+ // Find out whether we use `xsave'. (Preserve ebx.)
+#if CPUFAM_X86
+ push ebx
+#endif
+ mov eax, 0x01
+ cpuid
+ test ecx, 1 << 26
+ je 5f
+
+ // We have the `xsave' machinery. Select the base address.
+ lea R_si(r), [R_sp(r) + WORDSZ + regmap_size + 63]
+ and R_si(r), ~63
+ mov [R_bp(r) + regmap_fx], R_si(r)
+
+ // Clear out the header area.
+ xor eax, eax
+ lea R_di(r), [R_si(r) + 512]
+ mov ecx, 16
+ rep stosd
+
+ // Save the registers.
+ mov eax, 0x00000007
+ xor edx, edx
+ xsave [R_si(r)]
+
+ // Establish the AVX pointer, if available.
+ test dword ptr [R_si(r) + 512], 4 // = xstate_bv
+ je 8f
+
+ mov eax, 13
+ mov ecx, 2
+ cpuid
+ add R_b(r), R_si(r)
+ mov [R_bp(r) + regmap_avx], R_b(r)
+
+ jmp 8f
+
+ // We have only `fxsave'. Set the base address.
+5: lea R_si(r), [R_sp(r) + WORDSZ + regmap_size + 15]
+ and R_si(r), ~15
+ mov [R_bp(r) + regmap_fx], R_si(r)
+
+ // Save the registers.
+ fxsave [R_si(r)]
+
+ // Clear the x87 state; otherwise it can cause trouble later.
+8: fninit
+
+ // Done.
+#if CPUFAM_X86
+ pop ebx
+#endif
+ ret
+
+ENDFUNC
+
+FUNC(regdump_xtrstr)
+ endprologue
+ // On entry, r/ebp points to a register-save map. On exit, the
+ // extended registers are restored from the save area; r/ebp is left
+ // pointing to the general-purpose save area, ebx is preserved on
+ // 32-bit x86, and the other general registers are clobbered.
+
+ // Find the extended register dump.
+ mov R_si(r), [R_bp(r) + regmap_fx]
+
+ // Probe to find out whether we have `xsave'.
+#if CPUFAM_X86
+ push ebx
+#endif
+ mov eax, 0x01
+ cpuid
+ test ecx, 1 << 26
+ je 1f
+
+ // We have the `xsave' machinery.
+ mov eax, 0x00000007
+ xor edx, edx
+ xrstor [R_si(r)]
+ jmp 8f
+
+ // We must fake it up.
+1: fxrstor [R_si(r)]
+
+ // Done.
+8: mov R_bp(r), [R_bp(r) + regmap_gp]
+#if CPUFAM_X86
+ pop ebx
+#endif
+ ret
+
+ENDFUNC
+
+///----- That's all, folks --------------------------------------------------
--- /dev/null
+/* -*-c-*-
+ *
+ * Register dumping and other diagnostic tools for assembler code
+ *
+ * (c) 2016 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "config.h"
+
+#include <assert.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/macros.h>
+
+#include "dispatch.h"
+#include "regdump.h"
+
+/*----- Low-level printing ------------------------------------------------*/
+
+/* Currently these are good for all of our targets. */
+#define STEP_8 1
+#define TY_HEX_8 uint8
+#define P_HEX_8 "0x%02x"
+#define TY_UNSGN_8 uint8
+#define P_UNSGN_8 "%3u"
+#define PV_CHR_8 " `%c'"
+#define PV_HEX_8 " %02x"
+#define PV_UNSGN_8 "%4u"
+
+#define STEP_16 2
+#define TY_HEX_16 uint16
+#define P_HEX_16 "0x%04x"
+#define TY_UNSGN_16 uint16
+#define P_UNSGN_16 "%5u"
+#define TY_SGN_16 int16
+#define P_SGN_16 "%6d"
+#define PV_HEX_16 " 0x%04x"
+#define PV_UNSGN_16 "%9u"
+#define PV_SGN_16 "%9d"
+
+#define STEP_32 4
+#define TY_HEX_32 uint32
+#define P_HEX_32 "0x%08x"
+#define TY_UNSGN_32 uint32
+#define P_UNSGN_32 "%10u"
+#define TY_SGN_32 int32
+#define P_SGN_32 "%11d"
+#define TY_FLT_32 float
+#define P_FLT_32 "%15.9g"
+#define PV_HEX_32 " 0x%08x"
+#define PV_UNSGN_32 "%19u"
+#define PV_SGN_32 "%19d"
+#define PV_FLT_32 "%19.9g"
+
+#if ULONG_MAX >> 31 > 0xffffffff
+# define PL64 "l"
+#else
+# define PL64 "ll"
+#endif
+#define STEP_64 8
+#define TY_HEX_64 uint64
+#define P_HEX_64 "0x%016"PL64"x"
+#define TY_UNSGN_64 uint64
+#define P_UNSGN_64 "%20"PL64"u"
+#define TY_SGN_64 int64
+#define P_SGN_64 "%20"PL64"d"
+#define TY_FLT_64 double
+#define P_FLT_64 "%24.17g"
+#define PV_HEX_64 " 0x%016"PL64"x"
+#define PV_UNSGN_64 "%39"PL64"u"
+#define PV_SGN_64 "%39"PL64"d"
+#define PV_FLT_64 "%39.17g"
+
+#if CPUFAM_X86
+# define STEP_80 12
+#endif
+#if CPUFAM_AMD64
+# define STEP_80 16
+#endif
+#define TY_FLT_80 long double
+#define P_FLT_80 "%29.21Lg"
+#define PV_FLT_80 P_FLT_80
+
+#if CPUFAM_X86 || CPUFAM_AMD64
+# define ARCH_FORMATS(_) \
+ _(80, FLT)
+#endif
+#ifndef ARCH_FORMATS
+# define ARCH_FORMATS(_)
+#endif
+
+#define FORMATS(_) \
+ ARCH_FORMATS(_) \
+ _(64, HEX) _(64, FLT) _(64, UNSGN) _(64, SGN) \
+ _(32, HEX) _(32, FLT) _(32, UNSGN) _(32, SGN) \
+ _(16, HEX) _(16, UNSGN) _(16, SGN) \
+ _(8, HEX) _(8, CHR) _(8, UNSGN)
+
+struct fmtinfo {
+ const unsigned char *p;
+ unsigned wd, f;
+#define FMTF_VECTOR 1u
+};
+
+#define FMTFUNC_STD(w, fmt) \
+ static void dump_##fmt##_##w(struct fmtinfo *fmt) \
+ { \
+ TY_##fmt##_##w x = *(const TY_##fmt##_##w *)fmt->p; \
+ \
+ if (fmt->f&FMTF_VECTOR) printf(PV_##fmt##_##w, x); \
+ else printf(P_##fmt##_##w, x); \
+ fmt->p += STEP_##w; fmt->wd += 8*STEP_##w; \
+ }
+
+#define FMTFUNC_HEX(w) FMTFUNC_STD(w, HEX)
+#define FMTFUNC_UNSGN(w) FMTFUNC_STD(w, UNSGN)
+#define FMTFUNC_SGN(w) FMTFUNC_STD(w, SGN)
+#define FMTFUNC_FLT(w) FMTFUNC_STD(w, FLT)
+#define FMTFUNC_CHR(w)
+
+static void dump_CHR_8(struct fmtinfo *fmt)
+{
+ unsigned char x = *(const unsigned char *)fmt->p;
+
+ if (x < 32 || x > 126) printf("\\x%02x", x);
+ else printf(" `%c'", x);
+ fmt->p += 1; fmt->wd += 8;
+}
+
+#define FMTFUNC(w, fmt) FMTFUNC_##fmt(w)
+FORMATS(FMTFUNC)
+#undef FMTFUNC
+
+static const struct fmttab {
+ uint32 mask;
+ void (*fmt)(struct fmtinfo *);
+} fmttab[] = {
+#define FMTTAB(wd, fmt) { REGF_##fmt | REGF_##wd, dump_##fmt##_##wd },
+ FORMATS(FMTTAB)
+#undef FMTTAB
+ { 0, 0 }
+};
+
+/*----- Common subroutines ------------------------------------------------*/
+
+/* --- @regwd@ --- *
+ *
+ * Arguments: @uint32 f@ = format control word; see @REGF_...@
+ *
+ * Returns: The actual width of the operand, in bits.
+ *
+ * Use: If the operand is a vector (the @REGF_WDMASK@ field is
+ * nonzero) then return the width it denotes; otherwise, return
+ * the largest width implied by the @REGF_TYMASK@ field.
+ */
+
+static unsigned regwd(uint32 f)
+{
+ unsigned wd = 1 << ((f®F_WDMASK) >> REGF_WDSHIFT);
+
+ if (wd > 1) return (wd);
+ else if (f®F_80) return (80);
+ else if (f®F_64) return (64);
+ else if (f®F_32) return (32);
+ else if (f®F_16) return (16);
+ else if (f®F_8) return (8);
+ else { assert(0); return (1); }
+}
+
+/* --- @regname@ --- *
+ *
+ * Arguments: @char *buf = pointer to output buffer@
+ * @uint32 f@ = format control word; see @REGF_...@
+ *
+ * Returns: Pointer to name string.
+ *
+ * Use: Return a pointer to the name of the register implied by @f@,
+ * or null if there is no register. Systematic register names
+ * can be built in the provided buffer.
+ */
+
+static const char *regname(char *buf, uint32 f)
+{
+ unsigned wd = regwd(f);
+ unsigned src = f®F_SRCMASK;
+ unsigned ix = (f®F_IXMASK) >> REGF_IXSHIFT;
+ char *p = buf;
+
+ switch (src) {
+
+ case REGSRC_ABS:
+ return (0);
+
+#if CPUFAM_X86 || CPUFAM_AMD64
+ case REGSRC_GP:
+ if (ix == REGIX_FLAGS) {
+ if (wd == 64) *p++ = 'r';
+ else if (wd == 32) *p++ = 'e';
+ else if (wd != 16) assert(0);
+ p += sprintf(p, "flags");
+#if CPUFAM_AMD64
+ } else if (REGIX_R8 <= ix && ix <= REGIX_R15) {
+ p += sprintf(p, "r%u", ix - REGIX_R8 + 8);
+ switch (wd) {
+ case 64: break;
+ case 32: *p++ = 'd'; break;
+ case 16: *p++ = 'w'; break;
+ case 8: *p++ = 'l'; break;
+ default: assert(0);
+ }
+# endif
+ } else {
+ if (wd == 64) *p++ = 'r';
+ else if (wd == 32) *p++ = 'e';
+ switch (ix) {
+ case REGIX_IP: *p++ = 'i'; *p++ = 'p'; goto longreg;
+ case REGIX_AX: *p++ = 'a'; goto shortreg;
+ case REGIX_BX: *p++ = 'b'; goto shortreg;
+ case REGIX_CX: *p++ = 'c'; goto shortreg;
+ case REGIX_DX: *p++ = 'd'; goto shortreg;
+ case REGIX_SI: *p++ = 's'; *p++ = 'i'; goto longreg;
+ case REGIX_DI: *p++ = 'd'; *p++ = 'i'; goto longreg;
+ case REGIX_BP: *p++ = 'b'; *p++ = 'p'; goto longreg;
+ case REGIX_SP: *p++ = 's'; *p++ = 'p'; goto longreg;
+ default: assert(0);
+ }
+ if (0) {
+ shortreg:
+ switch (wd) {
+ case 64:
+ case 32:
+ case 16: *p++ = 'x'; break;
+ case 8: *p++ = 'l'; break;
+ default: assert(0);
+ }
+ } else {
+ longreg:
+ switch (wd) {
+ case 64:
+ case 32:
+ case 16: break;
+ case 8: *p++ = 'l'; break;
+ default: assert(0);
+ }
+ }
+ }
+ *p++ = 0;
+ return (buf);
+
+ case REGSRC_SEG:
+ assert(wd == 16);
+ switch (ix) {
+ case REGIX_CS: sprintf(buf, "cs"); break;
+ case REGIX_DS: sprintf(buf, "ds"); break;
+ case REGIX_SS: sprintf(buf, "ss"); break;
+ case REGIX_ES: sprintf(buf, "es"); break;
+ case REGIX_FS: sprintf(buf, "fs"); break;
+ case REGIX_GS: sprintf(buf, "gs"); break;
+ default: assert(0);
+ }
+ return (buf);
+
+ case REGSRC_STMMX:
+ if (ix == REGIX_FPFLAGS) return (0);
+ if (f®F_80) sprintf(buf, "st(%u)", ix);
+ else sprintf(buf, "mm%u", ix);
+ return (buf);
+
+ case REGSRC_SIMD:
+ if (ix == REGIX_FPFLAGS) return (0);
+ switch (wd) {
+ case 32: case 64: case 128: sprintf(buf, "xmm%u", ix); break;
+ case 256: sprintf(buf, "ymm%u", ix); break;
+ default: assert(0);
+ }
+ return (buf);
+#endif
+
+#if CPUFAM_ARMEL
+ case REGSRC_GP:
+ if (ix == REGIX_CPSR) sprintf(buf, "cpsr");
+ else if (ix == 15) sprintf(buf, "pc");
+ else sprintf(buf, "r%u", ix);
+ return (buf);
+ case REGSRC_FP:
+ if (ix == REGIX_FPSCR) sprintf(buf, "fpscr");
+ else {
+ switch (wd) {
+ case 32: *p++ = 's'; break;
+ case 64: *p++ = 'd'; break;
+ case 128: *p++ = 'q'; break;
+ default: assert(0);
+ }
+ p += sprintf(p, "%u", ix);
+ *p++ = 0;
+ }
+ return (buf);
+#endif
+
+#if CPUFAM_ARM64
+ case REGSRC_GP:
+ if (ix == REGIX_PC) sprintf(buf, "pc");
+ else if (ix == REGIX_NZCV) sprintf(buf, "nzcv");
+ else if (ix == 31 && wd == 64) sprintf(buf, "sp");
+ else {
+ switch (wd) {
+ case 32: *p++ = 'w'; break;
+ case 64: *p++ = 'x'; break;
+ default: assert(0);
+ }
+ p += sprintf(p, "%u", ix);
+ *p++ = 0;
+ }
+ return (buf);
+ case REGSRC_FP:
+ if (ix == REGIX_FPFLAGS) sprintf(buf, "fpflags");
+ else {
+ if (f®F_WDMASK)
+ *p++ = 'v';
+ else switch (wd) {
+ case 8: *p++ = 'b'; break;
+ case 16: *p++ = 'h'; break;
+ case 32: *p++ = 's'; break;
+ case 64: *p++ = 'd'; break;
+ default: assert(0);
+ }
+ p += sprintf(p, "%u", ix);
+ *p++ = 0;
+ }
+ return (buf);
+#endif
+
+ default:
+ assert(0);
+ return ("???");
+ }
+}
+
+/*----- x86 and AMD64 -----------------------------------------------------*/
+
+#if CPUFAM_X86 || CPUFAM_AMD64
+
+#if CPUFAM_X86
+# define P_HEX_GP "0x%08x"
+# define GP(gp) (gp).u32
+#endif
+#if CPUFAM_AMD64
+# define P_HEX_GP "0x%016"PL64"x"
+# define GP(gp) (gp).u64
+#endif
+
+void regdump_init(void) { ; }
+
+static void dump_flags(const char *lbl, const char *reg, gpreg f)
+{
+ printf(";; ");
+ if (lbl) printf("%s: ", lbl);
+ if (reg) printf("%s = ", reg);
+ printf(""P_HEX_GP"\n", GP(f));
+ printf(";;\t\tstatus: %ccf %cpf %caf %czf %csf %cdf %cof\n",
+ (GP(f) >> 0)&1u ? '+' : '-',
+ (GP(f) >> 2)&1u ? '+' : '-',
+ (GP(f) >> 4)&1u ? '+' : '-',
+ (GP(f) >> 6)&1u ? '+' : '-',
+ (GP(f) >> 7)&1u ? '+' : '-',
+ (GP(f) >> 10)&1u ? '+' : '-',
+ (GP(f) >> 11)&1u ? '+' : '-');
+ printf(";;\t\tsystem: %ctf %cif iopl=%d %cnt "
+ "%crf %cvm %cac %cvif %cvip %cid\n",
+ (GP(f) >> 8)&1u ? '+' : '-',
+ (GP(f) >> 9)&1u ? '+' : '-',
+ (int)((GP(f) >> 12)&1u),
+ (GP(f) >> 14)&1u ? '+' : '-',
+ (GP(f) >> 16)&1u ? '+' : '-',
+ (GP(f) >> 17)&1u ? '+' : '-',
+ (GP(f) >> 18)&1u ? '+' : '-',
+ (GP(f) >> 19)&1u ? '+' : '-',
+ (GP(f) >> 20)&1u ? '+' : '-',
+ (GP(f) >> 21)&1u ? '+' : '-');
+}
+
+static const char
+ *pcmap[] = { "sgl", "???", "dbl", "ext" },
+ *rcmap[] = { "nr", "-∞", "+∞", "0" };
+
+static void dump_fpflags(const char *lbl, const struct fxsave *fx)
+{
+ unsigned top = (fx->fsw >> 11)&7u;
+ unsigned tag = fx->ftw;
+ int skip = lbl ? strlen(lbl) + 2 : 0;
+
+ printf(";; ");
+ if (lbl) printf("%s: ", lbl);
+
+ printf(" fcw = 0x%04x: "
+ "%cim %cdm %czm %com %cum %cpm pc=%s rc=%s %cx\n",
+ fx->fcw,
+ (fx->fcw >> 0)&1u ? '+' : '-',
+ (fx->fcw >> 1)&1u ? '+' : '-',
+ (fx->fcw >> 2)&1u ? '+' : '-',
+ (fx->fcw >> 3)&1u ? '+' : '-',
+ (fx->fcw >> 4)&1u ? '+' : '-',
+ (fx->fcw >> 5)&1u ? '+' : '-',
+ pcmap[(fx->fcw >> 8)&3u],
+ rcmap[(fx->fcw >> 10)&3u],
+ (fx->fcw >> 12)&1u ? '+' : '-');
+ printf(";; %*s fsw = 0x%04x: "
+ "%cie %cde %cze %coe %cue %cpe %csf %ces %cc0 %cc1 %cc2 %cc3 "
+ "top=%d %cb\n",
+ skip, "",
+ fx->fsw,
+ (fx->fsw >> 0)&1u ? '+' : '-',
+ (fx->fsw >> 1)&1u ? '+' : '-',
+ (fx->fsw >> 2)&1u ? '+' : '-',
+ (fx->fsw >> 3)&1u ? '+' : '-',
+ (fx->fsw >> 4)&1u ? '+' : '-',
+ (fx->fsw >> 5)&1u ? '+' : '-',
+ (fx->fsw >> 6)&1u ? '+' : '-',
+ (fx->fsw >> 7)&1u ? '+' : '-',
+ (fx->fsw >> 8)&1u ? '+' : '-',
+ (fx->fsw >> 9)&1u ? '+' : '-',
+ (fx->fsw >> 10)&1u ? '+' : '-',
+ (fx->fsw >> 14)&1u ? '+' : '-',
+ top,
+ (fx->fsw >> 15)&1u ? '+' : '-');
+ printf(";; %*s ftw = 0x%02x\n", skip, "", tag);
+}
+
+static void dump_mxflags(const char *lbl, const struct fxsave *fx)
+{
+ printf(";; ");
+ if (lbl) printf("%s: ", lbl);
+
+ printf(" mxcsr = 0x%08x\n"
+ ";;\t\tmask = %cim %cdm %czm %com %cum %cpm\n"
+ ";;\t\t exc = %cie %cde %cze %coe %cue %cpe\n"
+ ";;\t\tmisc = %cdaz %cftz rc=%s\n",
+ fx->mxcsr,
+ (fx->mxcsr >> 7)&1u ? '+' : '-',
+ (fx->mxcsr >> 8)&1u ? '+' : '-',
+ (fx->mxcsr >> 9)&1u ? '+' : '-',
+ (fx->mxcsr >> 10)&1u ? '+' : '-',
+ (fx->mxcsr >> 11)&1u ? '+' : '-',
+ (fx->mxcsr >> 12)&1u ? '+' : '-',
+ (fx->mxcsr >> 0)&1u ? '+' : '-',
+ (fx->mxcsr >> 1)&1u ? '+' : '-',
+ (fx->mxcsr >> 2)&1u ? '+' : '-',
+ (fx->mxcsr >> 3)&1u ? '+' : '-',
+ (fx->mxcsr >> 4)&1u ? '+' : '-',
+ (fx->mxcsr >> 5)&1u ? '+' : '-',
+ (fx->mxcsr >> 6)&1u ? '+' : '-',
+ (fx->mxcsr >> 15)&1u ? '+' : '-',
+ rcmap[(fx->mxcsr >> 13)&3u]);
+}
+
+#if CPUFAM_X86
+# define REGF_GPWD REGF_32
+#endif
+#if CPUFAM_AMD64
+# define REGF_GPWD REGF_64
+#endif
+
+void regdump_gp(const struct regmap *map)
+{
+ unsigned i;
+
+ printf(";; General-purpose registers:\n");
+ for (i = REGIX_AX; i < REGIX_GPLIM; i++)
+ regdump(map, 0,
+ REGF_HEX | REGF_UNSGN | REGF_SGN | REGF_GPWD | REGSRC_GP | i);
+ regdump(map, 0, REGF_HEX | REGF_GPWD | REGSRC_GP | REGIX_IP);
+
+ printf(";; Segment registers:\n");
+ for (i = 0; i < REGIX_SEGLIM; i++)
+ regdump(map, 0, REGF_HEX | REGF_16 | REGSRC_SEG | i);
+
+ printf(";; Flags:\n");
+ regdump(map, 0, REGSRC_GP | REGF_GPWD | REGIX_FLAGS);
+}
+
+void regdump_fp(const struct regmap *map)
+{
+ unsigned top = (map->fx->fsw >> 11)&7u;
+ unsigned tag = map->fx->ftw;
+ unsigned i;
+
+ printf(";; Floating-point/MMX registers:\n");
+ if (!top && tag == 0xff)
+ for (i = 0; i < 8; i++)
+ regdump(map, 0,
+ REGF_HEX | REGF_UNSGN | REGF_SGN | REGF_CHR |
+ REGF_32 | REGF_16 | REGF_8 |
+ REGSRC_STMMX | i | (6 << REGF_WDSHIFT));
+ if (tag)
+ for (i = 0; i < 8; i++)
+ regdump(map, 0, REGF_FLT | REGF_80 | REGSRC_STMMX | i);
+
+ printf(";; Floating-point state:\n");
+ dump_fpflags(0, map->fx);
+}
+
+void regdump_simd(const struct regmap *map)
+{
+ unsigned f = REGF_HEX | REGF_FLT | REGF_UNSGN | REGF_SGN | REGF_CHR |
+ REGF_64 | REGF_32 | REGF_16 | REGF_8 |
+ REGSRC_SIMD;
+ unsigned i;
+
+ if (map->avx) f |= 8 << REGF_WDSHIFT;
+ else f |= 7 << REGF_WDSHIFT;
+
+ printf(";; SSE/AVX registers:\n");
+ for (i = 0; i < N(map->fx->xmm); i++)
+ regdump(map, 0, f | i);
+
+ printf(";; SSE/AVX floating-point state:\n");
+ dump_mxflags(0, map->fx);
+}
+
+#endif
+
+/*----- ARM32 -------------------------------------------------------------*/
+
+#if CPUFAM_ARMEL
+
+unsigned regdump__flags = 0;
+
+void regdump_init(void)
+{
+ if (cpu_feature_p(CPUFEAT_ARM_VFP)) regdump__flags |= REGF_VFP;
+ if (cpu_feature_p(CPUFEAT_ARM_D32)) regdump__flags |= REGF_D32;
+}
+
+static void dump_flags(const char *lbl, unsigned f)
+{
+ static const char
+ *modetab[] = { "?00", "?01", "?02", "?03", "?04", "?05", "?06", "?07",
+ "?08", "?09", "?10", "?11", "?12", "?13", "?14", "?15",
+ "usr", "fiq", "irq", "svc", "?20", "?21", "mon", "abt",
+ "?24", "?25", "hyp", "und", "?28", "?29", "?30", "sys" },
+ *condtab[] = { "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
+ "hi", "ls", "ge", "lt", "gt", "le", "al", "nv" };
+
+ printf(";; ");
+ if (lbl) printf("%s: ", lbl);
+ printf(" cpsr = 0x%08x\n", f);
+ printf(";;\t\tuser: %cn %cz %cc %cv %cq ge=%c%c%c%c\n",
+ (f >> 31)&1u ? '+' : '-',
+ (f >> 30)&1u ? '+' : '-',
+ (f >> 29)&1u ? '+' : '-',
+ (f >> 28)&1u ? '+' : '-',
+ (f >> 27)&1u ? '+' : '-',
+ (f >> 19)&1u ? '1' : '0',
+ (f >> 18)&1u ? '1' : '0',
+ (f >> 17)&1u ? '1' : '0',
+ (f >> 16)&1u ? '1' : '0');
+ printf(";;\t\tsystem: %cj it=%s:%c%c%c%c %ce %ca %ci %cf %ct m=%s\n",
+ (f >> 24)&1u ? '+' : '-',
+ condtab[(f >> 12)&15u],
+ (f >> 11)&1u ? '1' : '0',
+ (f >> 10)&1u ? '1' : '0',
+ (f >> 26)&1u ? '1' : '0',
+ (f >> 25)&1u ? '1' : '0',
+ (f >> 9)&1u ? '+' : '-',
+ (f >> 8)&1u ? '+' : '-',
+ (f >> 7)&1u ? '+' : '-',
+ (f >> 6)&1u ? '+' : '-',
+ (f >> 5)&1u ? '+' : '-',
+ modetab[(f >> 0)&31u]);
+}
+
+static void dump_fpflags(const char *lbl, unsigned f)
+{
+ static const char *rcmap[] = { "nr", "+∞", "-∞", "0" };
+
+ printf(";; ");
+ if (lbl) printf("%s: ", lbl);
+ printf(" fpscr = 0x%08x\n", f);
+ printf(";;\t\tcond: %cn %cz %cc %cv %cqc\n",
+ (f >> 31)&1u ? '+' : '-',
+ (f >> 30)&1u ? '+' : '-',
+ (f >> 29)&1u ? '+' : '-',
+ (f >> 28)&1u ? '+' : '-',
+ (f >> 27)&1u ? '+' : '-');
+ printf(";;\t\ttrap: %cide %cixe %cufe %cofe %cdze %cioe\n",
+ (f >> 15)&1u ? '+' : '-',
+ (f >> 12)&1u ? '+' : '-',
+ (f >> 11)&1u ? '+' : '-',
+ (f >> 10)&1u ? '+' : '-',
+ (f >> 9)&1u ? '+' : '-',
+ (f >> 8)&1u ? '+' : '-');
+ printf(";;\t\terror: %cide %cixe %cufe %cofe %cdze %cioe\n",
+ (f >> 7)&1u ? '+' : '-',
+ (f >> 4)&1u ? '+' : '-',
+ (f >> 3)&1u ? '+' : '-',
+ (f >> 2)&1u ? '+' : '-',
+ (f >> 1)&1u ? '+' : '-',
+ (f >> 0)&1u ? '+' : '-');
+ printf(";;\t\tcontrol: %cahp %cdn %cfz rm=%s str=%d len=%d\n",
+ (f >> 26)&1u ? '+' : '-',
+ (f >> 25)&1u ? '+' : '-',
+ (f >> 24)&1u ? '+' : '-',
+ rcmap[(f >> 22)&3u],
+ (f >> 20)&3u,
+ (f >> 16)&7u);
+}
+
+void regdump_gp(const struct regmap *map)
+{
+ unsigned i;
+
+ printf(";; General-purpose registers:\n");
+ for (i = 0; i < 16; i++)
+ regdump(map, 0,
+ REGF_HEX | REGF_UNSGN | REGF_SGN | REGF_32 | REGSRC_GP | i);
+
+ printf(";; Flags:\n");
+ regdump(map, 0, REGSRC_GP | REGF_32 | REGIX_CPSR);
+}
+
+void regdump_fp(const struct regmap *map)
+{
+ unsigned i, n;
+
+ if (!(regdump__flags®F_VFP)) {
+ printf(";; Floating-point and SIMD not available\n");
+ return;
+ }
+
+ printf(";; Floating-point/SIMD registers:\n");
+ if (regdump__flags®F_D32) n = 32;
+ else n = 16;
+ for (i = 0; i < n; i++)
+ regdump(map, 0,
+ REGF_HEX | REGF_UNSGN | REGF_SGN | REGF_FLT | REGF_CHR |
+ REGF_64 | REGF_32 | REGF_16 | REGF_8 |
+ REGSRC_SIMD | i | (6 << REGF_WDSHIFT));
+
+ printf(";; Floating-point state:\n");
+ dump_fpflags(0, map->fp->fpscr);
+}
+
+void regdump_simd(const struct regmap *map) { ; }
+
+#endif
+
+/*----- ARM64 -------------------------------------------------------------*/
+
+#if CPUFAM_ARM64
+
+void regdump_init(void) { ; }
+
+static void dump_flags(const char *lbl, unsigned f)
+{
+ printf(";; ");
+ if (lbl) printf("%s: ", lbl);
+ printf(" nzcv = 0x%08x\n", f);
+ printf(";;\t\tuser: %cn %cz %cc %cv\n",
+ (f >> 31)&1u ? '+' : '-',
+ (f >> 30)&1u ? '+' : '-',
+ (f >> 29)&1u ? '+' : '-',
+ (f >> 28)&1u ? '+' : '-');
+}
+
+static void dump_fpflags(const char *lbl, const struct fpsave *fp)
+{
+ static const char *rcmap[] = { "nr", "+∞", "-∞", "0" };
+ int skip = lbl ? strlen(lbl) + 2 : 0;
+
+ printf(";; ");
+ if (lbl) printf("%s: ", lbl);
+ printf(" fpsr = 0x%08x\n", fp->fpsr);
+ printf(";;\t\tcond: %cn %cz %cc %cv %cqc\n",
+ (fp->fpsr >> 31)&1u ? '+' : '-',
+ (fp->fpsr >> 30)&1u ? '+' : '-',
+ (fp->fpsr >> 29)&1u ? '+' : '-',
+ (fp->fpsr >> 28)&1u ? '+' : '-',
+ (fp->fpsr >> 27)&1u ? '+' : '-');
+ printf(";;\t\terror: %cidc %cixc %cufc %cofc %cdzc %cioc\n",
+ (fp->fpsr >> 7)&1u ? '+' : '-',
+ (fp->fpsr >> 4)&1u ? '+' : '-',
+ (fp->fpsr >> 3)&1u ? '+' : '-',
+ (fp->fpsr >> 2)&1u ? '+' : '-',
+ (fp->fpsr >> 1)&1u ? '+' : '-',
+ (fp->fpsr >> 0)&1u ? '+' : '-');
+ printf(";; %*s fpcr = 0x%08x\n", skip, "", fp->fpcr);
+ printf(";;\t\ttrap: %cide %cixe %cufe %cofe %cdze %cioe\n",
+ (fp->fpcr >> 15)&1u ? '+' : '-',
+ (fp->fpcr >> 12)&1u ? '+' : '-',
+ (fp->fpcr >> 11)&1u ? '+' : '-',
+ (fp->fpcr >> 10)&1u ? '+' : '-',
+ (fp->fpcr >> 9)&1u ? '+' : '-',
+ (fp->fpcr >> 8)&1u ? '+' : '-');
+ printf(";;\t\tcontrol: %cahp %cdn %cfz rm=%s str=%d len=%d\n",
+ (fp->fpcr >> 26)&1u ? '+' : '-',
+ (fp->fpcr >> 25)&1u ? '+' : '-',
+ (fp->fpcr >> 24)&1u ? '+' : '-',
+ rcmap[(fp->fpcr >> 22)&3u],
+ (fp->fpcr >> 20)&3u,
+ (fp->fpcr >> 16)&7u);
+}
+
+void regdump_gp(const struct regmap *map)
+{
+ unsigned i;
+
+ printf(";; General-purpose registers:\n");
+ for (i = 0; i < 32; i++)
+ regdump(map, 0,
+ REGF_HEX | REGF_UNSGN | REGF_SGN | REGF_64 | REGSRC_GP | i);
+ regdump(map, 0, REGF_HEX | REGF_64 | REGSRC_GP | REGIX_PC);
+
+ printf(";; Flags:\n");
+ regdump(map, 0, REGSRC_GP | REGF_32 | REGIX_NZCV);
+}
+
+void regdump_fp(const struct regmap *map)
+{
+ unsigned i;
+
+ printf(";; Floating-point/SIMD registers:\n");
+ for (i = 0; i < 32; i++)
+ regdump(map, 0,
+ REGF_HEX | REGF_UNSGN | REGF_SGN | REGF_FLT | REGF_CHR |
+ REGF_64 | REGF_32 | REGF_16 | REGF_8 |
+ REGSRC_SIMD | i | (7 << REGF_WDSHIFT));
+
+ printf(";; Floating-point state:\n");
+ dump_fpflags(0, map->fp);
+}
+
+void regdump_simd(const struct regmap *map) { ; }
+
+#endif
+
+/*----- The main entry point ----------------------------------------------*/
+
+/* --- @regdump@ --- *
+ *
+ * Arguments: @const void *base@ = pointer to base structure, corresponding
+ * to the @REGF_SRCMASK@ part of @f@
+ * @const char *lbl@ = label to print
+ * @uint32 f@ = format control word; see @REGF_...@
+ *
+ * Returns: ---
+ *
+ * Use: Dump a register value, or chunk of memory.
+ *
+ * This function is not usually called directly; instead, use
+ * the `reg' or `mem' assembler macros.
+ */
+
+void regdump(const void *base, const char *lbl, uint32 f)
+{
+ unsigned ix = (f®F_IXMASK) >> REGF_IXSHIFT;
+ unsigned wd = 1 << ((f®F_WDMASK) >> REGF_WDSHIFT);
+ unsigned fmt, ty;
+ uint32 fmtbit, tybit;
+ const void *p;
+ char regbuf[8]; const char *reg = regname(regbuf, f);
+ const struct regmap *map;
+ const struct fmttab *tab;
+ struct fmtinfo fi;
+ int firstp = 1;
+ int skip;
+ size_t n;
+
+#if CPUFAM_X86 || CPUFAM_AMD64
+ union vreg vr;
+#endif
+
+ if (reg) {
+ n = strlen(reg);
+ if (n < 7) {
+ memmove(regbuf + 7 - n, reg, n + 1);
+ memset(regbuf, ' ', 7 - n);
+ }
+ }
+
+ switch (f®F_SRCMASK) {
+ case REGSRC_ABS:
+ p = base;
+ break;
+
+#if CPUFAM_X86 || CPUFAM_AMD64
+ case REGSRC_GP:
+ map = (const struct regmap *)base;
+ if (ix == REGIX_FLAGS && !(f®F_FMTMASK))
+ { dump_flags(lbl, reg, map->gp->gp[REGIX_FLAGS]); return; }
+ p = &map->gp->gp[ix];
+ break;
+ case REGSRC_SEG:
+ map = (const struct regmap *)base;
+ assert(wd == 1); assert((f®F_TYMASK) == REGF_16);
+ p = &map->gp->seg[ix];
+ break;
+ case REGSRC_STMMX:
+ map = (const struct regmap *)base;
+ if (ix == REGIX_FPFLAGS)
+ { assert(!(f®F_FMTMASK)); dump_fpflags(lbl, map->fx); return; }
+ if (!((map->fx->ftw << ix)&128u)) {
+ printf(";; ");
+ if (lbl) printf("%s: ", lbl);
+ if (reg) printf("%s = ", reg);
+ printf(" dead\n");
+ return;
+ }
+ p = &map->fx->stmmx[ix];
+ break;
+ case REGSRC_SIMD:
+ map = (const struct regmap *)base;
+ if (ix == REGIX_FPFLAGS)
+ { assert(!(f®F_FMTMASK)); dump_mxflags(lbl, map->fx); return; }
+ if (wd <= 128)
+ p = &map->fx->xmm[ix];
+ else {
+ vr.v128[0] = map->fx->xmm[ix];
+ vr.v128[1] = map->avx->ymmh[ix];
+ assert(wd == 256);
+ p = &vr;
+ }
+ break;
+#endif
+
+#if CPUFAM_ARMEL
+ case REGSRC_GP:
+ map = (const struct regmap *)base;
+ if (ix == REGIX_CPSR && !(f®F_FMTMASK))
+ { dump_flags(lbl, map->gp->r[REGIX_CPSR].u32); return; }
+ p = &map->gp->r[ix];
+ break;
+ case REGSRC_FP:
+ case REGSRC_SIMD:
+ map = (const struct regmap *)base;
+ if (ix == REGIX_FPSCR) {
+ assert(!(f®F_FMTMASK));
+ dump_fpflags(lbl, map->fp->fpscr);
+ return;
+ }
+ switch (regwd(f)) {
+ case 32: p = &map->fp->u.s[ix]; break;
+ case 64: p = &map->fp->u.d[ix]; break;
+ case 128: p = &map->fp->u.q[ix]; break;
+ default: assert(0);
+ }
+ break;
+#endif
+
+#if CPUFAM_ARM64
+ case REGSRC_GP:
+ map = (const struct regmap *)base;
+ if (ix == REGIX_NZCV && !(f®F_FMTMASK))
+ { dump_flags(lbl, map->gp->r[REGIX_NZCV].u64); return; }
+ p = &map->gp->r[ix];
+ break;
+ case REGSRC_FP:
+ case REGSRC_SIMD:
+ map = (const struct regmap *)base;
+ if (ix == REGIX_FPFLAGS)
+ { assert(!(f®F_FMTMASK)); dump_fpflags(lbl, map->fp); return; }
+ p = &map->fp->v[ix];
+ break;
+#endif
+
+ default:
+ assert(0);
+ }
+
+ skip = (lbl ? strlen(lbl) + 2 : 0) + (reg ? strlen(reg) : 0);
+ fi.f = 0; if (wd > 1) fi.f |= FMTF_VECTOR;
+
+ for (ty = (f®F_TYMASK) >> REGF_TYSHIFT,
+ tybit = 1 << REGF_TYSHIFT;
+ ty;
+ ty >>= 1, tybit <<= 1) {
+ if (!(ty&1u)) continue;
+
+ for (fmt = (f®F_FMTMASK) >> REGF_FMTSHIFT,
+ fmtbit = 1 << REGF_FMTSHIFT;
+ fmt;
+ fmt >>= 1, fmtbit <<= 1) {
+
+ if (!(fmt&1u)) continue;
+
+ for (tab = fmttab; tab->mask; tab++)
+ if (tab->mask == (fmtbit | tybit)) goto found;
+ continue;
+ found:
+
+ if (firstp) {
+ printf(";;");
+ if (lbl) printf(" %s:", lbl);
+ if (reg) printf(" %s =", reg);
+ firstp = 0;
+ } else if (wd > 1)
+ printf("\n;; %*s =", skip, "");
+ else
+ fputs(" =", stdout);
+
+ fi.p = p; fi.wd = 0;
+ while (fi.wd < wd) { putchar(' '); tab->fmt(&fi); }
+ }
+ }
+ putchar('\n');
+}
+
+/*----- Other random utilities --------------------------------------------*/
+
+/* --- @regdump_freshline@ --- *
+ *
+ * Arguments: ---
+ *
+ * Returns: ---
+ *
+ * Use: Begin a fresh line of output.
+ */
+
+void regdump_freshline(void) { putchar('\n'); }
+
+/*----- That's all, folks -------------------------------------------------*/
--- /dev/null
+/* -*-c-*-
+ *
+ * Register dump and debugging support
+ *
+ * (c) 2019 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef CATACOMB_REGDUMP_H
+#define CATACOMB_REGDUMP_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "config.h"
+
+#ifndef ENABLE_ASM_DEBUG
+# error "Assembler-level debug disabled by `configure' script."
+#endif
+
+#if __ASSEMBLER__
+# include "asm-common.h"
+#else
+# include <float.h>
+# include <mLib/bits.h>
+#endif
+
+/*----- Random utilities --------------------------------------------------*/
+
+#define DO8(_) \
+ _(0) _(1) _(2) _(3) _(4) _(5) _(6) _(7)
+#define DOHI8(_) \
+ _(8) _(9) _(10) _(11) _(12) _(13) _(14) _(15)
+
+#define DO16(_) DO8(_) DOHI8(_)
+
+#define DO32(_) \
+ DO16(_) \
+ _(16) _(17) _(18) _(19) _(20) _(21) _(22) _(23) \
+ _(24) _(25) _(26) _(27) _(28) _(29) _(30) _(31)
+
+/*----- Common data structures --------------------------------------------*/
+
+#if !__ASSEMBLER__
+
+/* The following are good on our assembler targets. */
+typedef signed char int8;
+typedef short int16;
+typedef int int32;
+#if LONG_MAX >> 31 > 0x7fffffff
+ typedef long int64;
+#else
+ typedef long long int64;
+#endif
+typedef float float32;
+typedef double float64;
+typedef long double float80;
+
+#if CPUFAM_X86 || CPUFAM_ARMEL
+# define PTR32 void *p;
+# define PTR64
+#endif
+#if CPUFAM_AMD64 || CPUFAM_ARM64
+# define PTR32
+# define PTR64 void *p;
+#endif
+
+#define SIMD_COMMON(wd) \
+ uint8 u8[wd/8]; \
+ int8 i8[wd/8]; \
+ uint16 u16[wd/16]; \
+ int16 i16[wd/16]; \
+ uint32 u32[wd/32]; \
+ int32 i32[wd/32]; \
+ uint64 u64[wd/64]; \
+ int64 i64[wd/64]; \
+ float32 f32[wd/32]; \
+ float64 f64[wd/64]
+
+union gp32 { uint32 u32; int32 i32; PTR32 };
+union gp64 { uint64 u64; int64 i64; PTR64 };
+
+#endif
+
+/*----- Format word layout ------------------------------------------------*/
+
+#define REGF_IXMASK 0x000000ff
+#define REGF_IXSHIFT 0
+/* The index into the vector indicated by `REGF_SRCMASK', if applicable. */
+
+#define REGF_FMTMASK 0x0000ff00
+#define REGF_FMTSHIFT 8
+#define REGF_HEX 0x00000100
+#define REGF_CHR 0x00000200
+#define REGF_FLT 0x00000400
+#define REGF_UNSGN 0x00000800
+#define REGF_SGN 0x00001000
+/* How to format the value(s) found. */
+
+#define REGF_TYMASK 0x00ff0000
+#define REGF_TYSHIFT 16
+#define REGF_80 0x00010000
+#define REGF_64 0x00020000
+#define REGF_32 0x00040000
+#define REGF_16 0x00080000
+#define REGF_8 0x00100000
+/* Size of the value(s) to dump. */
+
+#define REGF_SRCMASK 0x0f000000
+#define REGSRC_ABS 0x01000000 /* absolute address */
+#define REGSRC_GP 0x02000000 /* general-purpose register */
+#define REGSRC_FP 0x03000000 /* floating-point register */
+#define REGSRC_SIMD 0x04000000 /* SIMD vector register */
+#define REGSRC_STMMX 0x05000000 /* x86-specific: x87/MMX register */
+#define REGSRC_SEG 0x06000000 /* x86-specific: segment register */
+/* Where to find the values. */
+
+#define REGF_WDMASK 0xf0000000
+#define REGF_WDSHIFT 28
+/* If we're to print a scalar, this is zero; otherwise, log_2 of the vector
+ * register width, in bits.
+ */
+
+/*----- x86 and AMD64 -----------------------------------------------------*/
+
+#if CPUFAM_X86 || CPUFAM_AMD64
+
+#define REGIX_FLAGS 0
+#define REGIX_IP 1
+#define REGIX_ADDR 2
+#define REGIX_AX 3
+#define REGIX_BX 4
+#define REGIX_CX 5
+#define REGIX_DX 6
+#define REGIX_SI 7
+#define REGIX_DI 8
+#define REGIX_BP 9
+#define REGIX_SP 10
+#if CPUFAM_X86
+# define REGIX_GPLIM 11
+#endif
+#if CPUFAM_AMD64
+# define REGIX_R8 11
+# define REGIX_R9 12
+# define REGIX_R10 13
+# define REGIX_R11 14
+# define REGIX_R12 15
+# define REGIX_R13 16
+# define REGIX_R14 17
+# define REGIX_R15 18
+# define REGIX_GPLIM 19
+#endif
+
+#define REGIX_CS 0
+#define REGIX_DS 1
+#define REGIX_SS 2
+#define REGIX_ES 3
+#define REGIX_FS 4
+#define REGIX_GS 5
+#define REGIX_SEGLIM 6
+
+#define REGIX_FPFLAGS 255
+
+#if !__ASSEMBLER__
+
+#if CPUFAM_X86
+typedef union gp32 gpreg;
+#endif
+#if CPUFAM_AMD64
+typedef union gp64 gpreg;
+#endif
+
+struct gpsave {
+ gpreg gp[REGIX_GPLIM];
+ uint16 seg[REGIX_SEGLIM];
+};
+
+union stmmx {
+ SIMD_COMMON(64);
+#if FLT_RADIX == 2 && LDBL_MANT_DIG == 64
+ long double f80;
+#endif
+unsigned char _pad[16];
+};
+
+union xmm { SIMD_COMMON(128); };
+union ymm { SIMD_COMMON(256); };
+union vreg { union xmm v128[2]; union ymm v256; };
+
+struct fxsave {
+ unsigned short fcw;
+ unsigned short fsw;
+ unsigned char ftw;
+ unsigned char _res0;
+ unsigned short fop;
+#if CPUFAM_X86
+ unsigned int fpu_ip;
+ unsigned short fpu_cs;
+ unsigned short _res1;
+ unsigned int fpu_dp;
+ unsigned short fpu_ds;
+ unsigned short _res2;
+#endif
+#if CPUFAM_AMD64
+ unsigned long long fpu_ip;
+ unsigned long long fpu_dp;
+#endif
+ unsigned int mxcsr;
+ unsigned int mxcsr_mask;
+
+ union stmmx stmmx[8];
+
+#if CPUFAM_X86
+ union xmm xmm[8];
+ unsigned char _pad0[8*16];
+#endif
+#if CPUFAM_AMD64
+ union xmm xmm[16];
+#endif
+
+ unsigned char _pad1[96];
+};
+
+struct xsave_avx {
+#if CPUFAM_X86
+ union xmm ymmh[8];
+ unsigned char _pad0[8*16];
+#endif
+#if CPUFAM_AMD64
+ union xmm ymmh[16];
+#endif
+};
+
+struct regmap {
+ struct gpsave *gp;
+ struct fxsave *fx;
+ struct xsave_avx *avx;
+};
+
+#else
+
+ .extern regdump_gpsave
+ .extern regdump_xtsave
+ .extern regdump_xtrstr
+ .extern regdump_gprstr
+
+ regmap_gp = 0*WORDSZ
+ regmap_fx = 1*WORDSZ
+ regmap_avx = 2*WORDSZ
+ regmap_size = 3*WORDSZ
+
+#define REGDEF_GPX86_COMMON(rn, RN) \
+ regsrc.e##rn = REGSRC_GP | REGIX_##RN; \
+ regty.e##rn = REGF_32; \
+ regfmt.e##rn = REGF_HEX; \
+ regsrc.r##rn = REGSRC_GP | REGIX_##RN; \
+ regty.r##rn = REGF_64; \
+ regfmt.r##rn = REGF_HEX
+
+#define REGDEF_GPX86_ABCD(rn, RN) \
+ regsrc.rn##hl = (4 << REGF_WDSHIFT) | REGSRC_GP | REGIX_##RN##X; \
+ regty.rn##hl = REGF_8; \
+ regfmt.rn##hl = REGF_HEX; \
+ regsrc.rn##l = REGSRC_GP | REGIX_##RN##X; \
+ regty.rn##l = REGF_8; \
+ regfmt.rn##l = REGF_HEX; \
+ regsrc.rn##x = REGSRC_GP | REGIX_##RN##X; \
+ regty.rn##x = REGF_16; \
+ regfmt.rn##x = REGF_HEX; \
+ REGDEF_GPX86_COMMON(rn##x, RN##X)
+REGDEF_GPX86_ABCD(a, A)
+REGDEF_GPX86_ABCD(b, B)
+REGDEF_GPX86_ABCD(c, C)
+REGDEF_GPX86_ABCD(d, D)
+
+ regsrc.eflags = REGSRC_GP | REGIX_FLAGS
+ regty.eflags = REGF_32
+ regfmt.eflags = 0
+
+#if CPUFAM_AMD64
+ regsrc.rflags = REGSRC_GP | REGIX_FLAGS
+ regty.rflags = REGF_64
+ regfmt.rflags = 0
+#endif
+
+#define REGDEF_GPX86_XP(rn, RN) \
+ regsrc.rn##l = REGSRC_GP | REGIX_##RN; \
+ regty.rn##l = REGF_8; \
+ regfmt.rn##l = REGF_HEX; \
+ regsrc.rn = REGSRC_GP | REGIX_##RN; \
+ regty.rn = REGF_16; \
+ regfmt.rn = REGF_HEX; \
+ REGDEF_GPX86_COMMON(rn, RN)
+REGDEF_GPX86_XP(ip, IP)
+REGDEF_GPX86_XP(si, SI)
+REGDEF_GPX86_XP(di, DI)
+REGDEF_GPX86_XP(bp, BP)
+REGDEF_GPX86_XP(sp, SP)
+
+#if CPUFAM_AMD64
+# define REGDEF_GPAMD64(i) \
+ regsrc.r##i##b = REGSRC_GP | REGIX_R##i; \
+ regty.r##i##b = REGF_8; \
+ regfmt.r##i##b = REGF_HEX; \
+ regsrc.r##i##w = REGSRC_GP | REGIX_R##i; \
+ regty.r##i##w = REGF_16; \
+ regfmt.r##i##w = REGF_HEX; \
+ regsrc.r##i##d = REGSRC_GP | REGIX_R##i; \
+ regty.r##i##d = REGF_32; \
+ regfmt.r##i##d = REGF_HEX; \
+ regsrc.r##i = REGSRC_GP | REGIX_R##i; \
+ regty.r##i = REGF_64; \
+ regfmt.r##i = REGF_HEX;
+ DOHI8(REGDEF_GPAMD64)
+#endif
+
+#define REGDEF_SEG(rn, RN) \
+ regsrc.rn = REGSRC_SEG | REGIX_##RN; \
+ regty.rn = REGF_16; \
+ regfmt.rn = REGF_HEX
+REGDEF_SEG(ss, SS)
+REGDEF_SEG(cs, CS)
+REGDEF_SEG(ds, DS)
+REGDEF_SEG(es, ES)
+REGDEF_SEG(fs, FS)
+REGDEF_SEG(gs, GS)
+
+#define REGDEF_STMMX(i) \
+ regsrc.st##i = REGSRC_STMMX | i; \
+ regty.st##i = REGF_80; \
+ regfmt.st##i = REGF_FLT; \
+ regsrc.mm##i = (6 << REGF_WDSHIFT) | REGSRC_STMMX | i; \
+ regty.mm##i = REGF_16; \
+ regfmt.mm##i = REGF_HEX;
+DO8(REGDEF_STMMX)
+
+#define REGDEF_SIMD(i) \
+ regsrc.xmm##i = (7 << REGF_WDSHIFT) | REGSRC_SIMD | i; \
+ regty.xmm##i = REGF_32; \
+ regfmt.xmm##i = REGF_HEX; \
+ regsrc.ymm##i = (8 << REGF_WDSHIFT) | REGSRC_SIMD | i; \
+ regty.ymm##i = REGF_32; \
+ regfmt.ymm##i = REGF_HEX;
+DO8(REGDEF_SIMD)
+#if CPUFAM_AMD64
+ DOHI8(REGDEF_SIMD)
+#endif
+
+ REGDUMP_GPSIZE = REGIX_GPLIM*WORDSZ + REGIX_SEGLIM*2
+
+# if CPUFAM_AMD64 && ABI_SYSV
+ REGDUMP_SPADJ = REGDUMP_GPSIZE + WORDSZ + 128
+# else
+ REGDUMP_SPADJ = REGDUMP_GPSIZE + WORDSZ
+# endif
+
+.macro _saveregs addr=nil
+ // Save the registers, leaving r/ebp pointing to the register map.
+
+ // Stash r/eax. This is bletcherous: hope we don't get a signal in
+ // the next few instructions.
+ mov [R_sp(r) - REGDUMP_SPADJ + (REGIX_AX - 1)*WORDSZ], R_a(r)
+
+ .ifnes "\addr", "nil"
+ // Collect the effective address for the following dump, leaving it
+ // in the `addr' slot of the dump.
+ lea R_a(r), \addr
+ mov [R_sp(r) - REGDUMP_SPADJ + (REGIX_ADDR - 1)*WORDSZ], R_a(r)
+ .endif
+
+ // Make space for the register save area. On AMD64 with System/V
+ // ABI, also skip the red zone. Use `lea' here to preserve the
+ // flags.
+ lea R_sp(r), [R_sp(r) - REGDUMP_SPADJ]
+
+ // Save flags and general-purpose registers. On 32-bit x86, we save
+ // ebx here and establish a GOT pointer here for the benefit of the
+ // PLT-indirect calls made later on.
+ pushf
+# if CPUFAM_X86
+ mov [esp + 4*REGIX_BX], ebx
+ ldgot
+# endif
+ callext F(regdump_gpsave)
+
+ // Make space for the extended registers.
+ sub R_sp(r), R_c(r)
+ callext F(regdump_xtsave)
+
+ // Prepare for calling back into C. On 32-bit x86, leave space for
+ // the arguments and set up the GOT pointer; on AMD64 Windows, leave
+ // the `shadow space' for the called-function's arguments. Also,
+ // forcibly align the stack pointer to a 16-byte boundary.
+# if CPUFAM_X86
+ sub esp, 16
+# elif ABI_WIN
+ sub rsp, 32
+# endif
+ and R_sp(r), ~15
+.endm
+
+.macro _rstrregs
+ // Restore registers.
+
+ // We assume r/ebp still points to the register map.
+ callext F(regdump_xtrstr)
+ mov R_sp(r), R_bp(r)
+ callext F(regdump_gprstr)
+ popf
+ lea R_sp(r), [R_sp(r) + REGDUMP_SPADJ]
+.endm
+
+.macro _regbase
+# if CPUFAM_X86
+ mov [esp + 0], ebp
+# elif ABI_SYSV
+ mov rdi, rbp
+# elif ABI_WIN
+ mov rcx, rbp
+# endif
+.endm
+
+.macro _membase
+ mov R_a(r), [R_bp(r) + regmap_gp]
+# if CPUFAM_X86
+ mov eax, [eax + REGIX_ADDR*WORDSZ]
+ mov [esp + 0], eax
+# elif ABI_SYSV
+ mov rdi, [rax + REGIX_ADDR*WORDSZ]
+# elif ABI_WIN
+ mov rcx, [rax + REGIX_ADDR*WORDSZ]
+# endif
+.endm
+
+.macro _reglbl msg
+ .ifeqs "\msg", ""
+# if CPUFAM_X86
+ mov dword ptr [esp + 4], 0
+# elif ABI_SYSV
+ xor esi, esi
+# elif ABI_WIN
+ xor edx, edx
+# endif
+ .else
+# if CPUFAM_X86
+ lea eax, [INTADDR(.L$_reglbl$\@)]
+ mov [esp + 4], eax
+# elif ABI_SYSV
+ lea rsi, [INTADDR(.L$_reglbl$\@)]
+# elif ABI_WIN
+ lea rdx, [INTADDR(.L$_reglbl$\@)]
+# endif
+ _LIT
+.L$_reglbl$\@:
+ .asciz "\msg"
+ _ENDLIT
+ .endif
+.endm
+
+.macro _regfmt arg
+# if CPUFAM_X86
+ mov dword ptr [esp + 8], \arg
+# elif ABI_SYSV
+ mov edx, \arg
+# elif ABI_WIN
+ mov r8d, \arg
+# endif
+.endm
+
+#endif
+
+#endif
+
+/*----- ARM32 -------------------------------------------------------------*/
+
+#if CPUFAM_ARMEL
+
+#if !__ASSEMBLER__
+extern unsigned regdump__flags;
+#endif
+#define REGF_VFP 1u
+#define REGF_D32 2u
+
+#define REGIX_CPSR 16
+#define REGIX_ADDR 17
+#define REGIX_GPLIM 18
+
+#define REGIX_FPSCR 255
+
+#if !__ASSEMBLER__
+
+union neon64 { SIMD_COMMON(64); };
+union neon128 { SIMD_COMMON(128); };
+
+struct gpsave { union gp32 r[REGIX_GPLIM]; };
+
+struct fpsave {
+ unsigned fpscr;
+ unsigned _pad0;
+ union {
+ float32 s[32];
+ union neon64 d[32];
+ union neon128 q[16];
+ } u;
+};
+
+struct regmap {
+ struct gpsave *gp;
+ struct fpsave *fp;
+};
+
+#else
+
+ .extern regdump_gpsave
+ .extern regdump_xtsave
+ .extern regdump_xtrstr
+ .extern regdump_gprstr
+
+ regmap_gp = 0
+ regmap_fp = 4
+ regmap_size = 8
+
+#define REGDEF_GP(i) \
+ regsrc.r##i = REGSRC_GP | i; \
+ regty.r##i = REGF_32; \
+ regfmt.r##i = REGF_HEX;
+DO16(REGDEF_GP)
+
+ regsrc.cpsr = REGSRC_GP | REGIX_CPSR
+ regty.cpsr = REGF_32
+ regfmt.cpsr = 0
+
+#define REGDEF_NEONS(i) \
+ regsrc.s##i = REGSRC_FP | i; \
+ regty.s##i = REGF_32; \
+ regfmt.s##i = REGF_FLT;
+DO32(REGDEF_NEONS)
+
+#define REGDEF_NEOND(i) \
+ regsrc.d##i = (6 << REGF_WDSHIFT) | REGSRC_FP | i; \
+ regty.d##i = REGF_32; \
+ regfmt.d##i = REGF_HEX;
+DO32(REGDEF_NEOND)
+
+#define REGDEF_NEONQ(i) \
+ regsrc.q##i = (7 << REGF_WDSHIFT) | REGSRC_FP | i; \
+ regty.q##i = REGF_32; \
+ regfmt.q##i = REGF_HEX;
+DO16(REGDEF_NEONQ)
+
+ regsrc.fpscr = REGSRC_FP | REGIX_FPSCR
+ regty.fpscr = REGF_32
+ regfmt.fpscr = 0
+
+ REGDUMP_GPSIZE = 4*REGIX_GPLIM
+ REGDUMP_FPSIZE_D16 = 8 + 16*8
+ REGDUMP_FPSIZE_D32 = 8 + 32*8
+
+.macro _saveregs base=nil, off=#0
+ // Save the registers, leaving r4 pointing to the register map.
+
+ // Stash r14. This is bletcherous: hope we don't get a signal in
+ // the next few instructions.
+ str r14, [r13, #-REGDUMP_GPSIZE + 14*4]
+
+ .ifnes "\base,\off", "nil,#0"
+ // Collect the effective address for the following dump, leaving it
+ // in the `addr' slot of the dump.
+ .ifeqs "\base", "nil"
+ adrl r14, \off
+ .else
+ add r14, \base, \off
+ .endif
+ str r14, [r13, #-REGDUMP_GPSIZE + 4*REGIX_ADDR]
+ .endif
+
+ // Make space for the register save area.
+ sub r13, r13, #REGDUMP_GPSIZE
+
+ // Save flags and general-purpose registers.
+ str r12, [r13, #4*12]
+ bl regdump_gpsave
+
+ // Make space for the extended registers.
+ sub r13, r13, r0
+ bl regdump_xtsave
+
+ // Prepare for calling back into C.
+ ldgot
+ mov r0, r13
+ bic r0, r0, #15
+ mov r13, r0
+.endm
+
+.macro _rstrregs
+ // Restore registers.
+
+ // We assume r4 still points to the register map.
+ bl regdump_xtrstr
+ mov r13, r4
+ bl regdump_gprstr
+ ldr r14, [r13, #14*4]
+ add r13, r13, #REGDUMP_GPSIZE
+.endm
+
+.macro _regbase
+ mov r0, r5
+.endm
+
+.macro _membase
+ mov r0, r6
+.endm
+
+.macro _reglbl msg
+ adrl r1, .L$_reglbl$\@
+ _LIT
+.L$_reglbl$\@:
+ .asciz "\msg"
+ .balign 4
+ _ENDLIT
+.endm
+
+.macro _regfmt arg
+ movw r2, #\arg&0xffff
+ movt r2, #(\arg >> 16)&0xffff
+.endm
+
+#endif
+
+#endif
+
+/*----- ARM64 -------------------------------------------------------------*/
+
+#if CPUFAM_ARM64
+
+#define REGIX_NZCV 32
+#define REGIX_PC 33
+#define REGIX_ADDR 34
+#define REGIX_GPLIM 36
+
+#define REGIX_FPFLAGS 255
+
+#if !__ASSEMBLER__
+
+union v128 { SIMD_COMMON(128); };
+
+struct gpsave { union gp64 r[REGIX_GPLIM]; };
+
+struct fpsave {
+ unsigned fpsr, fpcr;
+ union v128 v[32];
+};
+
+struct regmap {
+ struct gpsave *gp;
+ struct fpsave *fp;
+};
+
+#else
+
+ .extern regdump_gpsave
+ .extern regdump_xtsave
+ .extern regdump_xtrstr
+ .extern regdump_gprstr
+
+ regmap_gp = 0
+ regmap_fp = 8
+ regmap_size = 16
+
+#define REGDEF_GP(i) \
+ regsrc.x##i = REGSRC_GP | i; \
+ regty.x##i = REGF_64; \
+ regfmt.x##i = REGF_HEX; \
+ regsrc.w##i = REGSRC_GP | i; \
+ regty.w##i = REGF_32; \
+ regfmt.w##i = REGF_HEX;
+DO32(REGDEF_GP)
+
+ regsrc.sp = REGSRC_GP | 31
+ regty.sp = REGF_64
+ regfmt.sp = REGF_HEX
+
+ regsrc.pc = REGSRC_GP | REGIX_PC
+ regty.pc = REGF_64
+ regfmt.pc = REGF_HEX
+
+ regsrc.nzcv = REGSRC_GP | REGIX_NZCV
+ regty.nzcv = REGF_32
+ regfmt.nzcv = 0
+
+#define REGDEF_FP(i) \
+ regsrc.b##i = REGSRC_FP | i; \
+ regty.b##i = REGF_8; \
+ regfmt.b##i = REGF_HEX; \
+ regsrc.h##i = REGSRC_FP | i; \
+ regty.h##i = REGF_16; \
+ regfmt.h##i = REGF_HEX; \
+ regsrc.s##i = REGSRC_FP | i; \
+ regty.s##i = REGF_32; \
+ regfmt.s##i = REGF_FLT; \
+ regsrc.d##i = REGSRC_FP | i; \
+ regty.d##i = REGF_64; \
+ regfmt.d##i = REGF_FLT; \
+ regsrc.v##i = (7 << REGF_WDSHIFT) | REGSRC_FP | i; \
+ regty.v##i = REGF_32; \
+ regfmt.v##i = REGF_HEX;
+DO32(REGDEF_FP)
+
+ regsrc.fpflags = REGSRC_FP | REGIX_FPFLAGS
+ regty.fpflags = REGF_32
+ regfmt.fpflags = 0
+
+ REGDUMP_GPSIZE = 8*REGIX_GPLIM
+ REGDUMP_FPSIZE = 16 + 16 + 32*16
+
+.macro _saveregs base=nil, off=#0
+ // Save the registers, leaving x20 pointing to the register map.
+
+ // Stash x30. This is bletcherous: hope we don't get a signal in
+ // the next few instructions.
+ str x30, [sp, #-REGDUMP_GPSIZE + 30*8]
+
+ .ifnes "\base,\off", "nil,#0"
+ // Collect the effective address for the following dump, leaving it
+ // in the `addr' slot of the dump.
+ .ifeqs "\base", "nil"
+ adr x30, \off
+ .else
+ add x30, \base, \off
+ .endif
+ str x30, [sp, #-REGDUMP_GPSIZE + 8*REGIX_ADDR]
+ .endif
+
+ // Make space for the register save area.
+ sub sp, sp, #REGDUMP_GPSIZE
+
+ // Save flags and general-purpose registers.
+ stp x16, x17, [sp, #8*16]
+ bl regdump_gpsave
+
+ // Make space for the extended registers.
+ sub sp, sp, x0
+ bl regdump_xtsave
+.endm
+
+.macro _rstrregs
+ // Restore registers.
+
+ // We assume x21 still points to the register map.
+ bl regdump_xtrstr
+ mov sp, x20
+ bl regdump_gprstr
+ ldr x30, [sp, #30*8]
+ add sp, sp, #REGDUMP_GPSIZE
+.endm
+
+.macro _regbase
+ mov x0, x21
+.endm
+
+.macro _membase
+ mov x0, x22
+.endm
+
+.macro _reglbl msg
+ adr x1, .L$_reglbl$\@
+ _LIT
+.L$_reglbl$\@:
+ .asciz "\msg"
+ .balign 4
+ _ENDLIT
+.endm
+
+.macro _regfmt arg
+ movz w2, #\arg&0xffff
+ movk w2, #(\arg >> 16)&0xffff, lsl #16
+.endm
+
+#endif
+
+#endif
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @regdump_init@ --- *
+ *
+ * Arguments: ---
+ *
+ * Returns: ---
+ *
+ * Use: Performs one-time initialization for register dumping. In
+ * particular, this performs CPU feature detection on platforms
+ * where that is a difficult task: without it, registers
+ * corresponding to optional architectural features can be
+ * neither printed nor preserved by the register-dump machinery.
+ */
+
+#if !__ASSEMBLER__
+extern void regdump_init(void);
+#endif
+
+/* --- @regdump@ --- *
+ *
+ * Arguments: @const void *base@ = pointer to base structure, corresponding
+ * to the @REGF_SRCMASK@ part of @f@
+ * @const char *lbl@ = label to print
+ * @uint32 f@ = format control word; see @REGF_...@
+ *
+ * Returns: ---
+ *
+ * Use: Dump a register value, or chunk of memory.
+ *
+ * This function is not usually called directly; instead, use
+ * the `reg' or `mem' assembler macros.
+ */
+
+#if !__ASSEMBLER__
+extern void regdump(const void *base, const char *lbl, uint32 f);
+#else
+ .extern regdump
+#endif
+
+/* --- @regdump_gp@, @regdump_fp@, @regdump_simd@ --- *
+ *
+ * Arguments: @const struct regmap *map@ = pointer to register map
+ *
+ * Returns: ---
+ *
+ * Use: Dump the general-purpose/floating-point/SIMD registers.
+ *
+ * This function is not usually called directly; instead, use
+ * the `regdump' assembler macro.
+ */
+
+#if !__ASSEMBLER__
+extern void regdump_gp(const struct regmap */*map*/);
+extern void regdump_fp(const struct regmap */*map*/);
+extern void regdump_simd(const struct regmap */*map*/);
+#else
+ .extern regdump_gp
+ .extern regdump_fp
+ .extern regdump_simd
+#endif
+
+/* --- @regdump_freshline@ --- *
+ *
+ * Arguments: ---
+ *
+ * Returns: ---
+ *
+ * Use: Begin a fresh line of output.
+ */
+
+#if !__ASSEMBLER__
+extern void regdump_freshline(void);
+#else
+ .extern regdump_freshline
+#endif
+
+/*----- Main user interface macros ----------------------------------------*/
+
+#if __ASSEMBLER__
+
+.macro terpri
+ _saveregs
+ callext F(regdump_freshline)
+ _rstrregs
+.endm
+
+.macro reg lbl, rn, fmt=0
+ _saveregs
+ _regbase
+ _reglbl "\lbl"
+ .L$reg.fmt$\@ = regsrc.\rn | \fmt | \
+ (((\fmt®F_TYMASK) == 0)®ty.\rn) | \
+ (((\fmt®F_FMTMASK) == 0)®fmt.\rn)
+ _regfmt .L$reg.fmt$\@
+ callext F(regdump)
+ _rstrregs
+.endm
+
+.macro mem lbl, addr, fmt=0
+ _saveregs \addr
+ _membase
+ _reglbl "\lbl"
+ .L$mem.fmt$\@ = REGSRC_ABS | \fmt | \
+ (((\fmt®F_TYMASK) == 0)®F_32) | \
+ (((\fmt®F_FMTMASK) == 0)®F_HEX)
+ _regfmt .L$mem.fmt$\@
+ callext F(regdump)
+ _rstrregs
+.endm
+
+.macro regdump gp=nil, fp=nil, simd=nil
+ _saveregs
+ .ifnes "\gp", "nil"
+ _regbase
+ callext F(regdump_gp)
+ .endif
+ .ifnes "\fp", "nil"
+ _regbase
+ callext F(regdump_fp)
+ .endif
+ .ifnes "\simd", "nil"
+ _regbase
+ callext F(regdump_simd)
+ .endif
+ _rstrregs
+.endm
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
--- /dev/null
+/* -*-c-*-
+ *
+ * Reservoir and buffer handling
+ *
+ * (c) 2017 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "rsvr.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @rsvr_mkplan@ --- *
+ *
+ * Arguments: @rsvr_plan *plan@ = pointer to plan to fill in
+ * @const rsvr_policy *pol@ = reservoir policy to follow
+ * @size_t used@ = amount of data in the reservoir
+ * @size_t insz@ = amount of fresh input data arriving
+ *
+ * Returns: ---
+ *
+ * Use: Prepares a plan for feeding input data into a block-oriented
+ * operation.
+ *
+ * The caller's code for following the plan proceeds in four
+ * parts.
+ *
+ * 1. Insert the first @plan->head@ input items into the
+ * reservoir; there will be sufficient space, and
+ * @plan->head@ will be at most @pol->blksz@.
+ *
+ * 2. Process the first @plan->from_rsvr@ items from the
+ * reservoir, shifting the remaining items forward;
+ * @plan->from_rsvr@ will be a multiple of @pol->blksz@.
+ *
+ * 3. Process the next @plan->from_input@ items directly from
+ * the input; @plan->from_input@ will be a multiple of
+ * @pol->blksz@.
+ *
+ * 4. Insert the remaining @plan->tail@ input items into the
+ * reservoir for next time.
+ */
+
+void rsvr_mkplan(rsvr_plan *plan, const rsvr_policy *pol,
+ size_t used, size_t insz)
+{
+ unsigned extra = !!(pol->f&RSVRF_FULL);
+ unsigned n, final;
+
+ if (insz < pol->rsvrsz - used + extra) {
+ /* Easy case: there's enough space in the reservoir for the whole input,
+ * so just accumulate it and we're done.
+ */
+
+ plan->head = insz;
+ plan->from_rsvr = plan->from_input = plan->tail = 0;
+ } else {
+ /* The hard case. We're going to have to actually process something. */
+
+ /* Firstly, we top the reservoir up to the next block boundary. */
+ n = (pol->rsvrsz - used)%pol->blksz;
+ plan->head = n; used += n; insz -= n;
+
+ /* Next, figure out the final amount we'll leave in the reservoir. This
+ * will be congruent to USED, modulo the block size, and within the last
+ * BLKSZ-wide interval permitted. We must have enough material to get
+ * here, or we'd be in the other branch above.
+ */
+ final = pol->rsvrsz - pol->blksz + extra +
+ (insz + pol->blksz - extra)%pol->blksz;
+
+ /* If we don't have enough input to drain the reservoir completely, and
+ * then top it up to the necessary level, then take as much as we can
+ * from the reservoir; otherwise, drain completely and then use up the
+ * remaining input directly.
+ */
+ if (insz < final) {
+ /* We don't have enough input to drain the reservoir completely and
+ * then top it up to the necessary final level. Take what we can.
+ */
+
+ plan->from_rsvr = used + insz - final;
+ plan->from_input = 0;
+ plan->tail = insz;
+ } else {
+ /* We have lots of input. Drain the reservoir fully, process the bulk
+ * of the input buffer, and load the rest into the reservoir at the
+ * end.
+ */
+
+ plan->from_rsvr = used;
+ plan->from_input = insz - final;
+ plan->tail = final;
+ }
+ }
+}
+
+/* --- @rsvr_setup@ --- *
+ *
+ * Arguments: @rsvr_state *st@ = pointer to state structure to fill in
+ * @const rsvr_policy *pol@ = reservoir policy to follow
+ * @void *rsvr@ = pointer to the actual reservoir
+ * @unsigned *used@ = pointer to the reservoir level
+ * @const void *in@ = pointer to the input data
+ * @size_t insz@ = size of the input
+ *
+ * Returns: ---
+ *
+ * Use: Prepares for a simple operation. This performs the initial
+ * copy of input data into the reservoir, and prepares for the
+ * next step.
+ *
+ * After this, the calling code should usually proceed as
+ * follows.
+ *
+ * 1. Call @RSVR_NEXT@ in a sequence of loops, with
+ * successively smaller values of @n@, to process waiting
+ * data from the reservoir. Usually, each @n@ will be some
+ * multiple of the block size @pol->blksz@, and the final
+ * loop will have @n = pol->blksz@.
+ *
+ * 2. Call @rsvr_done@ to indicate that this has been done.
+ *
+ * 3. Call @RSVR_NEXT@ in a sequence of loops, as in step 1,
+ * to process the remaining data from the input buffer.
+ *
+ * 4. Call @rsvr_done@ to indicate that the job is complete.
+ */
+
+void rsvr_setup(rsvr_state *st, const rsvr_policy *pol,
+ void *rsvr, unsigned *used, const void *in, size_t insz)
+{
+ rsvr_mkplan(&st->plan, pol, *used, insz);
+ st->rsvr = rsvr; st->in = in; st->used = used;
+
+ if (st->plan.head) {
+ memcpy(rsvr + *st->used, st->in, st->plan.head);
+ *st->used += st->plan.head; st->in += st->plan.head;
+ }
+ st->src = RSVRSRC_RSVR; st->p = st->rsvr; st->sz = st->plan.from_rsvr;
+}
+
+/* --- @RSVR_NEXT@, @rsvr_next@ --- *
+ *
+ * Arguments: @rsvr_state *st@ = pointer to the state structure
+ * @size_t n@ = amount of input data required, in bytes; should
+ * usually be a multiple of @pol->blksz@
+ *
+ * Returns: A pointer to the next @n@ bytes of input, or null if there is
+ * insufficient data remaining.
+ */
+
+const void *rsvr_next(rsvr_state *st, size_t n) { return RSVR_NEXT(st, n); }
+
+/* --- @rsvr_done@ --- *
+ *
+ * Arguments: @rsvr_state *st@ = pointer to the state structure
+ *
+ * Returns: Zero after the first pass, nonzero after the second.
+ *
+ * Use: Reports that the first or second stage (see @rsvr_setup@
+ * above) of an operation has been completed.
+ *
+ * If the first stage is complete, then this shifts stuff about
+ * in the reservoir and prepares for the second stage; if the
+ * second stage is complete, then it copies the remaining input
+ * into the reservoir and marks the state as complete.
+ */
+
+int rsvr_done(rsvr_state *st)
+{
+ assert(!st->sz);
+ switch (st->src) {
+ case RSVRSRC_RSVR:
+ if (st->plan.from_rsvr) {
+ if (st->plan.from_rsvr < *st->used) {
+ memmove(st->rsvr, st->rsvr + st->plan.from_rsvr,
+ *st->used - st->plan.from_rsvr);
+ }
+ *st->used -= st->plan.from_rsvr;
+ }
+ st->src = RSVRSRC_INPUT;
+ st->p = st->in; st->sz = st->plan.from_input;
+ return (0);
+ case RSVRSRC_INPUT:
+ if (st->plan.tail) {
+ memcpy(st->rsvr + *st->used, st->p, st->plan.tail);
+ *st->used += st->plan.tail;
+ }
+ st->src = RSVRSRC_DONE;
+ st->p = 0; st->sz = 0;
+ return (1);
+ default:
+ abort();
+ }
+}
+
+/*----- Testing -----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include <mLib/alloc.h>
+#include <mLib/bits.h>
+#include <mLib/darray.h>
+#include <mLib/report.h>
+#include <mLib/testrig.h>
+
+struct rng {
+ uint32 x;
+};
+
+static void init_rng(struct rng *r)
+ { r->x = 0; }
+
+static void step_rng(struct rng *r)
+ { r->x = U32(0x0d83c207*r->x + 0x380fcfea); }
+
+DA_DECL(uint_v, unsigned);
+
+struct testinfo {
+ rsvr_policy pol;
+ uint_v chunksz;
+ uint_v blksz;
+ unsigned used;
+ size_t off;
+ int ok;
+};
+
+static void show_uint_v(const char *what, const uint_v *v)
+{
+ size_t i;
+
+ printf("\t%s:", what);
+ for (i = 0; i < DA_LEN(v); i++) printf("%s%u", i ? ", " : " ", DA(v)[i]);
+ printf("\n");
+}
+
+static void report_policy(const struct rsvr_policy *pol)
+{
+ printf("\tpolicy: flags = 0x%08x%s; blksz = %u; rsvrsz = %u\n",
+ pol->f, pol->f&RSVRF_FULL ? " full" : pol->f ? "" : " nil",
+ pol->blksz, pol->rsvrsz);
+}
+
+static void report_testinfo(const struct testinfo *info)
+{
+ report_policy(&info->pol);
+ show_uint_v("chunksz", &info->chunksz);
+ show_uint_v("blksz", &info->blksz);
+ printf("\treservoir level = %u\n", info->used);
+ printf("\toffset = %lu\n", (unsigned long)info->off);
+}
+
+static void check(struct rng *r, struct testinfo *info,
+ const void *p, size_t sz)
+{
+ const octet *q = p;
+ unsigned x;
+
+ while (sz) {
+ x = U8(r->x);
+ if (info->ok && *q != x) {
+ printf("\n*** FAIL data mismatch (0x%02x /= 0x%02x)\n", *q, x);
+ report_testinfo(info);
+ info->ok = 0;
+ }
+ q++; sz--; info->off++;
+ step_rng(r);
+ }
+}
+
+static void parse_intlist(uint_v *v, const char *p)
+{
+ char *q;
+ unsigned long n;
+ int e = errno;
+
+ for (;;) {
+ while (isspace((unsigned char)*p)) p++;
+ if (!*p) break;
+ if (*p == ',') p++;
+ while (isspace((unsigned char)*p)) p++;
+ errno = 0; n = strtoul(p, &q, 0);
+ if (errno || (*q && *q != ',' && !isspace((unsigned char)*q)))
+ die(1, "invalid int list");
+ p = q; DA_PUSH(v, n);
+ }
+ errno = e;
+}
+
+int vrfy_plan(dstr *dv)
+{
+ rsvr_policy pol;
+ rsvr_plan want, calc;
+ unsigned used;
+ size_t insz;
+ int ok = 1;
+
+ pol.f = *(unsigned long *)dv[0].buf;
+ pol.blksz = *(unsigned long *)dv[1].buf;
+ pol.rsvrsz = *(unsigned long *)dv[2].buf;
+ used = *(unsigned long *)dv[3].buf;
+ insz = *(unsigned long *)dv[4].buf;
+ want.head = *(unsigned long *)dv[5].buf;
+ want.from_rsvr = *(unsigned long *)dv[6].buf;
+ want.from_input = *(unsigned long *)dv[7].buf;
+ want.tail = *(unsigned long *)dv[8].buf;
+
+ rsvr_mkplan(&calc, &pol, used, insz);
+
+ if (want.head != calc.head ||
+ want.from_rsvr != calc.from_rsvr ||
+ want.from_input != calc.from_input ||
+ want.tail != calc.tail) {
+ printf("\n*** FAIL plan doesn't match\n");
+ report_policy(&pol);
+ printf("\treservoir level = %u\n", used);
+ printf("\tinput size = %lu\n", (unsigned long)insz);
+#define SHOW(what, slot) do { \
+ printf("\t" what " (calc) %lu %s %lu (want)\n", \
+ (unsigned long)calc.slot, \
+ calc.slot == want.slot ? "=" : "/=", \
+ (unsigned long)want.slot); \
+} while(0)
+ SHOW("head", head);
+ SHOW("from reservoir", from_rsvr);
+ SHOW("from input", from_input);
+ SHOW("tail", tail);
+#undef SHOW
+ ok = 0;
+ }
+
+ return (ok);
+}
+
+static int vrfy_copy(dstr *dv)
+{
+ struct testinfo info;
+ rsvr_state st;
+ struct rng ra, rb;
+ octet *buf = 0, *rsvr;
+ const void *p;
+ size_t i, j, bsz = 0;
+ unsigned n, used0, lb, ub, fin;
+
+ init_rng(&ra); init_rng(&rb);
+ info.pol.f = *(unsigned long *)dv[0].buf;
+ info.pol.blksz = *(unsigned long *)dv[1].buf;
+ info.pol.rsvrsz = *(unsigned long *)dv[2].buf;
+ info.ok = 1; info.used = 0; info.off = 0;
+ rsvr = xmalloc(info.pol.rsvrsz);
+ DA_CREATE(&info.chunksz); parse_intlist(&info.chunksz, dv[3].buf);
+ DA_CREATE(&info.blksz); parse_intlist(&info.blksz, dv[4].buf);
+ for (i = 0; i < DA_LEN(&info.chunksz); i++)
+ if (bsz < DA(&info.chunksz)[i]) bsz = DA(&info.chunksz)[i];
+ buf = xmalloc(bsz);
+ for (i = 0; i < DA_LEN(&info.chunksz); i++) {
+ n = DA(&info.chunksz)[i];
+ for (j = 0; j < n; j++) { buf[j] = U8(ra.x); step_rng(&ra); }
+ used0 = info.used;
+ rsvr_setup(&st, &info.pol, rsvr, &info.used, buf, n);
+ if (n != st.plan.head + st.plan.from_input + st.plan.tail) {
+ printf("\n*** FAIL input size crosscheck "
+ "(%u /= %u + %lu + %u = %lu)\n",
+ n,
+ st.plan.head, (unsigned long)st.plan.from_input, st.plan.tail,
+ (unsigned long)(st.plan.head +
+ st.plan.from_input +
+ st.plan.tail));
+ report_testinfo(&info);
+ info.ok = 0;
+ }
+ if (st.plan.from_rsvr%info.pol.blksz) {
+ printf("\n*** FAIL reservoir chunk %u misaligned\n",
+ st.plan.from_rsvr);
+ report_testinfo(&info);
+ info.ok = 0;
+ }
+ if (st.plan.from_input%info.pol.blksz) {
+ printf("\n*** FAIL direct chunk %lu misaligned\n",
+ (unsigned long)st.plan.from_input);
+ report_testinfo(&info);
+ info.ok = 0;
+ }
+ if (st.plan.head > info.pol.rsvrsz - used0) {
+ printf("\n*** FAIL top-up out of range (%u + %u = %u > %u)\n",
+ used0, st.plan.head, used0 + st.plan.head, info.pol.rsvrsz);
+ report_testinfo(&info);
+ info.ok = 0;
+ }
+ if (st.plan.from_rsvr > used0 + st.plan.head) {
+ printf("\n*** FAIL shift out of range (%u > %u + %u = %u)\n",
+ st.plan.from_rsvr,
+ used0, st.plan.head, used0 + st.plan.head);
+ report_testinfo(&info);
+ info.ok = 0;
+ }
+ if (st.plan.head != n) {
+ ub = info.pol.rsvrsz + !!(info.pol.f&RSVRF_FULL);
+ lb = ub - info.pol.blksz;
+ fin = used0 + st.plan.head - st.plan.from_rsvr + st.plan.tail;
+ if (lb > fin) {
+ printf("\n*** FAIL final level out of bounds "
+ "(%u > %u = %u + %u - %u + %u)\n",
+ lb, fin,
+ used0, st.plan.head, st.plan.from_rsvr, st.plan.tail);
+ report_testinfo(&info);
+ info.ok = 0;
+ }
+ if (fin >= ub) {
+ printf("\n*** FAIL final level out of bounds "
+ "(%u + %u - %u + %u = %u >= %u)\n",
+ used0, st.plan.head, st.plan.from_rsvr, st.plan.tail,
+ fin, ub);
+ report_testinfo(&info);
+ info.ok = 0;
+ }
+ }
+
+ if (!info.ok) break;
+ RSVR_DO(&st) {
+ for (j = 0; j < DA_LEN(&info.blksz); j++) {
+ n = DA(&info.blksz)[j];
+ while ((p = RSVR_NEXT(&st, n)) != 0) check(&rb, &info, p, n);
+ }
+ }
+ }
+
+ DA_DESTROY(&info.chunksz);
+ DA_DESTROY(&info.blksz);
+ xfree(rsvr); xfree(buf);
+ return (info.ok);
+}
+
+static const struct test_chunk tests[] = {
+ { "plan", vrfy_plan,
+ { &type_ulong, &type_ulong, &type_ulong, &type_ulong, &type_ulong,
+ &type_ulong, &type_ulong, &type_ulong, &type_ulong } },
+ { "copy", vrfy_copy,
+ { &type_ulong, &type_ulong, &type_ulong, &type_string, &type_string } },
+ { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+ test_run(argc, argv, tests, SRCDIR "/t/rsvr");
+ return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
--- /dev/null
+/* -*-c-*-
+ *
+ * Reservoir and buffer handling
+ *
+ * (c) 2017 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef CATACOMB_RSVR_H
+#define CATACOMB_RSVR_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct rsvr_policy {
+ unsigned f; /* Flags... */
+#define RSVRF_FULL 1u /* Hold back a full reservoir */
+ unsigned blksz; /* Block size */
+ unsigned rsvrsz; /* Reservoir size; multiple of
+ * @blksz@ */
+} rsvr_policy;
+
+typedef struct rsvr_plan {
+ unsigned head; /* First, accumulate @head@ bytes
+ * into the reservoir */
+ unsigned from_rsvr; /* Next, process @from_rsvr@ bytes
+ * from the reservoir */
+ size_t from_input; /* Then, process @from_input@ bytes
+ * directly from the input */
+ unsigned tail; /* Finally, accumulate the remaining
+ * @tail@ bytes of input into the
+ * reservoir */
+} rsvr_plan;
+
+enum { RSVRSRC_RSVR, RSVRSRC_INPUT, RSVRSRC_DONE };
+
+typedef struct rsvr_state {
+ rsvr_plan plan;
+ unsigned *used;
+ unsigned char *rsvr;
+ const unsigned char *in, *p;
+ size_t sz;
+ unsigned src;
+} rsvr_state;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @rsvr_mkplan@ --- *
+ *
+ * Arguments: @rsvr_plan *plan@ = pointer to plan to fill in
+ * @const rsvr_policy *pol@ = reservoir policy to follow
+ * @size_t used@ = amount of data in the reservoir
+ * @size_t insz@ = amount of fresh input data arriving
+ *
+ * Returns: ---
+ *
+ * Use: Prepares a plan for feeding input data into a block-oriented
+ * operation.
+ *
+ * The caller's code for following the plan proceeds in four
+ * parts.
+ *
+ * 1. Insert the first @plan->head@ input items into the
+ * reservoir; there will be sufficient space, and
+ * @plan->head@ will be at most @pol->blksz@.
+ *
+ * 2. Process the first @plan->from_rsvr@ items from the
+ * reservoir, shifting the remaining items forward;
+ * @plan->from_rsvr@ will be a multiple of @pol->blksz@.
+ *
+ * 3. Process the next @plan->from_input@ items directly from
+ * the input; @plan->from_input@ will be a multiple of
+ * @pol->blksz@.
+ *
+ * 4. Insert the remaining @plan->tail@ input items into the
+ * reservoir for next time.
+ */
+
+extern void rsvr_mkplan(rsvr_plan */*plan*/, const rsvr_policy */*pol*/,
+ size_t /*used*/, size_t /*insz*/);
+
+/* --- @rsvr_setup@ --- *
+ *
+ * Arguments: @rsvr_state *st@ = pointer to state structure to fill in
+ * @const rsvr_policy *pol@ = reservoir policy to follow
+ * @void *rsvr@ = pointer to the actual reservoir
+ * @unsigned *used@ = pointer to the reservoir level
+ * @const void *in@ = pointer to the input data
+ * @size_t insz@ = size of the input
+ *
+ * Returns: ---
+ *
+ * Use: Prepares for a simple operation. This performs the initial
+ * copy of input data into the reservoir, and prepares for the
+ * next step.
+ *
+ * After this, the calling code should usually proceed as
+ * follows.
+ *
+ * 1. Call @RSVR_NEXT@ in a sequence of loops, with
+ * successively smaller values of @n@, to process waiting
+ * data from the reservoir. Usually, each @n@ will be some
+ * multiple of the block size @pol->blksz@, and the final
+ * loop will have @n = pol->blksz@.
+ *
+ * 2. Call @rsvr_done@ to indicate that this has been done.
+ *
+ * 3. Call @RSVR_NEXT@ in a sequence of loops, as in step 1,
+ * to process the remaining data from the input buffer.
+ *
+ * 4. Call @rsvr_done@ to indicate that the job is complete.
+ */
+
+extern void rsvr_setup(rsvr_state */*st*/, const rsvr_policy */*pol*/,
+ void */*rsvr*/, unsigned */*used*/,
+ const void */*in*/, size_t /*insz*/);
+
+/* --- @RSVR_NEXT@, @rsvr_next@ --- *
+ *
+ * Arguments: @rsvr_state *st@ = pointer to the state structure
+ * @size_t n@ = amount of input data required, in bytes; should
+ * usually be a multiple of @pol->blksz@
+ *
+ * Returns: A pointer to the next @n@ bytes of input, or null if there is
+ * insufficient data remaining.
+ */
+
+#define RSVR_NEXT(st, n) \
+ ((n) > (st)->sz \
+ ? 0 \
+ : ((st)->sz -= (n), \
+ (st)->p += (n), \
+ (const void *)((st)->p - (n))))
+extern const void *rsvr_next(rsvr_state */*st*/, size_t /*n*/);
+
+/* --- @rsvr_done@ --- *
+ *
+ * Arguments: @rsvr_state *st@ = pointer to the state structure
+ *
+ * Returns: Zero after the first pass, nonzero after the second.
+ *
+ * Use: Reports that the first or second stage (see @rsvr_setup@
+ * above) of an operation has been completed.
+ *
+ * If the first stage is complete, then this shifts stuff about
+ * in the reservoir and prepares for the second stage; if the
+ * second stage is complete, then it copies the remaining input
+ * into the reservoir and marks the state as complete.
+ */
+
+extern int rsvr_done(rsvr_state */*st*/);
+
+/* --- @RSVR_DO@ --- *
+ *
+ * Arguments: @st@ = pointer to state structure
+ *
+ * Use: Invoke as @RSVR_DO(st) stmt@: performs two passes of @stmt@
+ * over the reservoir and input buffers respectively.
+ */
+
+#define RSVR_DO(st) switch (0) while (!rsvr_done(st)) case 0:
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
--- /dev/null
+### -*-conf-*-
+### Tests for reservoir management.
+
+plan {
+ ## F BLKSZ RSVRSZ USED INSZ HEAD FROM-RSVR FROM-INPUT TAIL
+ 0 8 8 0 0 0 0 0 0;
+ 0 8 8 0 1 1 0 0 0;
+ 0 8 8 7 1 1 8 0 0;
+ 1 8 8 7 1 1 0 0 0;
+ 0 8 8 0 16 0 0 16 0;
+ 0 8 8 1 15 7 8 8 0;
+ 1 8 8 1 15 7 8 0 8;
+ 0 8 8 1 16 7 8 8 1;
+ 1 8 8 1 16 7 8 8 1;
+
+ 0 8 8 0 1 1 0 0 0;
+ 0 8 8 1 4 4 0 0 0;
+ 0 8 8 5 7 3 8 0 4;
+ 0 8 8 4 31 4 8 24 3;
+ 0 8 8 3 5 5 8 0 0;
+}
+
+copy {
+ ## F BLKSZ RSVRSZ CHUNKSZ,... BLKSZ,...
+ 0 8 8 1,4,7,31,5 16,8;
+}
--- /dev/null
+#include "config.h"
+#include "asm-common.h"
+#include "regdump.h"
+
+ .text
+
+ .p2align 5
+vec:
+ .long 1, 2, 3, 4, 5, 6, 7, 8
+
+FUNC(main)
+
+ pushreg x29, x30
+ setfp
+ endprologue
+
+ bl regdump_init
+
+ cmp x0, x0
+ reg "simd", v1
+
+ mov w0, #0
+ dropfp
+ popreg x29, x30
+ ret
+
+ENDFUNC
--- /dev/null
+#include "config.h"
+#include "asm-common.h"
+#include "regdump.h"
+
+ .text
+ .arch armv7-a
+
+ .p2align 5
+vec:
+ .long 1, 2, 3, 4, 5, 6, 7, 8
+
+FUNC(main)
+
+ pushreg r11, r14
+ setfp
+ endprologue
+
+ bl regdump_init
+
+ cmp r0, r0
+ regdump gp=t
+ reg "general purpose", r1
+ reg " flags", cpsr
+ reg " simd", q0, fmt=REGF_HEX | REGF_32 | REGF_16
+ reg " float", d0, fmt=REGF_FLT | REGF_64
+ reg " float", s0
+ reg " float status", fpscr
+
+ mov r0, #0
+ dropfp
+ popreg r11, pc
+
+ENDFUNC
--- /dev/null
+#include "config.h"
+#include "asm-common.h"
+#include "regdump.h"
+
+ .text
+
+ .p2align 5
+vec:
+ .long 1, 2, 3, 4, 5, 6, 7, 8
+
+FUNC(main)
+
+ pushreg R_bp(r)
+ setfp
+ and R_sp(r), ~15
+ endprologue
+
+ fldz
+ fld1
+ fldpi
+ fldl2t
+ fldl2e
+ fldlg2
+ fldln2
+ //fld1
+
+ ldgot
+ movdqa xmm2, [INTADDR(vec)]
+ //vmovdqa ymm2, [INTADDR(vec)]
+
+ reg "my fp", xmm2, REGF_FLT | REGF_64 | REGF_32
+
+ xor eax, eax
+ dropfp
+ popreg R_bp(r)
+ ret
+
+ENDFUNC
;;m4_define([catacomb_seen_$3/$$2], [t])])])
catacomb_CPU_FAMILIES([_def])
nil) ;;
- *) AC_MSG_ERROR([BUG: unexpected $1 \`$1']) ;;
+ *) AC_MSG_ERROR([BUG: unexpected $1 \`$$1']) ;;
esac])
dnl Now that's out the way, we can explain what we're doing.
*) AC_MSG_RESULT([$CPUFAM/$ABI]) ;;
esac
+dnl Consider enabling support for assembler-level debugging toys.
+AC_ARG_ENABLE([asm-debug],
+ AS_HELP_STRING([--enable-asm-debug],
+ [enable assembler debugging features]),
+ [mdw_asm_debug=$enableval], [mdw_asm_debug=no])
+case $CPUFAM in nil) mdw_asm_debug=no ;; esac
+case $mdw_asm_debug in
+ no) ;;
+ *) AC_DEFINE([ENABLE_ASM_DEBUG], [1],
+ [Define to enable assembler-level debugging.]) ;;
+esac
+AM_CONDITIONAL([ASM_DEBUG], [test x$mdw_asm_debug != xno])
+
+dnl Check for leading underscores on C symbols.
+LT_SYS_SYMBOL_USCORE
+case $sys_symbol_underscore in
+ yes) AC_DEFINE([SYM_USCORE], [1],
+ [Define if C symbols are prefixed with an underscore.]) ;;
+esac
+
dnl--------------------------------------------------------------------------
dnl CPU-specific assembler features.
AC_CHECK_HEADERS([linux/auxvec.h])
AC_CHECK_FUNCS([getauxval])
+dnl Some equipment for measuring CPU performance.
+AC_CHECK_HEADERS([linux/perf_event.h])
+
dnl Find the bit lengths of the obvious integer types. This will be useful
dnl when deciding on a representation for multiprecision integers.
type_bits="" type_bits_sep=""
AC_SUBST([CATACOMB_LIBS])
dnl Necessary support libraries.
-PKG_CHECK_MODULES([mLib], [mLib >= 2.2.2.1])
+PKG_CHECK_MODULES([mLib], [mLib >= 2.3.0])
AM_CFLAGS="$AM_CFLAGS $mLib_CFLAGS"
dnl--------------------------------------------------------------------------
## dispatch
cpu_feature_p@Base 2.2.3
dispatch_debug@Base 2.2.3
+ (optional|arch=i386 amd64)dispatch_x86ish_cpuid@Base 2.5.0
+ (optional|arch=i386 amd64)dispatch_x86ish_xmmregisters_p@Base 2.5.0
+
+## regdump (available with `--enable-asm-debug')
+ (optional)regdump_init@Base 2.5.0
+ (optional)regdump@Base 2.5.0
+ (optional)regdump_freshline@Base 2.5.0
+ (optional)regdump_gp@Base 2.5.0
+ (optional)regdump_fp@Base 2.5.0
+ (optional)regdump_simd@Base 2.5.0
+ (optional)regdump_gprstr@Base 2.5.0
+ (optional)regdump_gpsave@Base 2.5.0
+ (optional)regdump_xtrstr@Base 2.5.0
+ (optional)regdump_xtsave@Base 2.5.0
+ (optional|arch=armel armhf)regdump__flags@Base 2.5.0
## keysz
keysz@Base 2.1.0
+ keysz_pad@Base 2.5.0
keysz_fromdl@Base 2.1.1
keysz_fromec@Base 2.1.1
keysz_fromif@Base 2.1.1
l_free@Base 2.1.0
l_purge@Base 2.1.0
+## rsvr
+ rsvr_setup@Base 2.5.0
+ rsvr_mkplan@Base 2.5.0
+ rsvr_next@Base 2.5.0
+ rsvr_done@Base 2.5.0
+
###--------------------------------------------------------------------------
### Mathematical infrastructure.
mpx_kmul@Base 2.1.1
mpx_ksqr@Base 2.1.1
(optional|arch=i386)mpx_umul4_x86_sse2@Base 2.3.0
+ (optional|arch=i386)mpx_umul4_x86_avx@Base 2.3.0
(optional|arch=amd64)mpx_umul4_amd64_sse2@Base 2.3.0
+ (optional|arch=amd64)mpx_umul4_amd64_avx@Base 2.3.0
(optional|arch=i386)mpxmont_mul4_x86_sse2@Base 2.3.0
+ (optional|arch=i386)mpxmont_mul4_x86_avx@Base 2.3.0
(optional|arch=amd64)mpxmont_mul4_amd64_sse2@Base 2.3.0
+ (optional|arch=amd64)mpxmont_mul4_amd64_avx@Base 2.3.0
(optional|arch=i386)mpxmont_redc4_x86_sse2@Base 2.3.0
+ (optional|arch=i386)mpxmont_redc4_x86_avx@Base 2.3.0
(optional|arch=amd64)mpxmont_redc4_amd64_sse2@Base 2.3.0
+ (optional|arch=amd64)mpxmont_redc4_amd64_avx@Base 2.3.0
## mparena
mparena_create@Base 2.0.0
pgen_filter@Base 2.1.1
pgen_test@Base 2.1.1
pgen_jump@Base 2.2.4
- pgen_primep@Base 2.1.1
+ pgen_granfrob@Base 2.5.0
+ pgen_primep@Base 2.5.0
pgen_gcdstep@Base 2.1.1
pgen_simulstep@Base 2.1.1
pgen_simultest@Base 2.1.1
strongprime@Base 2.3.1
## limlee
- limlee_step@Base 2.2.4
- limlee@Base 2.2.4
+ limlee_step@Base 2.5.1+
+ limlee@Base 2.5.1+
## gfx
gfx_acc@Base 2.0.0
ec_dbl@Base 2.2.0
ec_neg@Base 2.2.0
ec_sub@Base 2.2.0
- ec_imul@Base 2.2.0
- ec_mul@Base 2.2.0
- ec_immul@Base 2.2.0
- ec_mmul@Base 2.2.0
+ ec_imul@Base 2.5.1+
+ ec_mul@Base 2.5.1+
+ ec_immul@Base 2.5.1+
+ ec_mmul@Base 2.5.1+
ec_check@Base 2.2.0
ec_destroycurve@Base 2.2.0
ec_idfix@Base 2.2.0
## lcrand
lcrand@Base 2.0.0
- lcrand_create@Base 2.0.0
+ lcrand_create@Base 2.5.1+
lcrand_range@Base 2.0.0
## rand
rand_noisesrc@Base 2.2.3
rand_seed@Base 2.2.3
rand_quick@Base 2.2.3
- rand_key@Base 2.2.3
+ (optional|arch=i386 amd64)rand_quick_x86ish_rdrand@Base 2.5.0
+ rand_key@Base 2.5.1+
rand_add@Base 2.2.3
rand_goodbits@Base 2.2.3
rand_get@Base 2.2.3
gcipher_byname@Base 2.1.1
gciphertab@Base 2.1.1
+## gaead
+ gaead_byname@Base 2.5.0
+ gaead_encrypt@Base 2.5.0
+ gaead_decrypt@Base 2.5.0
+ gaeadtab@Base 2.5.0
+
## ghash
ghash_byname@Base 2.1.1
ghashtab@Base 2.1.1
gmac_byname@Base 2.1.1
gmactab@Base 2.1.1
+## ccm
+ ccm_check@Base 2.5.0
+ ccm_fmtctr@Base 2.5.0
+ ccm_fmthdr@Base 2.5.0
+
+## gcm
+ gcm_mktable@Base 2.5.0
+ gcm_ghashdone@Base 2.5.0
+ gcm_concat@Base 2.5.0
+ gcm_mulk_64b@Base 2.5.0
+ (optional|arch=i386 amd64)gcm_mulk_64b_x86ish_pclmul@Base 2.5.0
+ (optional|arch=i386 amd64)gcm_mulk_64b_x86ish_pclmul_avx@Base 2.5.0
+ (optional|arch=armel armhf)gcm_mulk_64b_arm_crypto@Base 2.5.0
+ (optional|arch=arm64)gcm_mulk_64b_arm64_pmull@Base 2.5.0
+ gcm_mulk_64l@Base 2.5.0
+ (optional|arch=i386 amd64)gcm_mulk_64l_x86ish_pclmul@Base 2.5.0
+ (optional|arch=i386 amd64)gcm_mulk_64l_x86ish_pclmul_avx@Base 2.5.0
+ (optional|arch=armel armhf)gcm_mulk_64l_arm_crypto@Base 2.5.0
+ (optional|arch=arm64)gcm_mulk_64l_arm64_pmull@Base 2.5.0
+ gcm_mulk_96b@Base 2.5.0
+ (optional|arch=i386 amd64)gcm_mulk_96b_x86ish_pclmul@Base 2.5.0
+ (optional|arch=i386 amd64)gcm_mulk_96b_x86ish_pclmul_avx@Base 2.5.0
+ (optional|arch=armel armhf)gcm_mulk_96b_arm_crypto@Base 2.5.0
+ (optional|arch=arm64)gcm_mulk_96b_arm64_pmull@Base 2.5.0
+ gcm_mulk_96l@Base 2.5.0
+ (optional|arch=i386 amd64)gcm_mulk_96l_x86ish_pclmul@Base 2.5.0
+ (optional|arch=i386 amd64)gcm_mulk_96l_x86ish_pclmul_avx@Base 2.5.0
+ (optional|arch=armel armhf)gcm_mulk_96l_arm_crypto@Base 2.5.0
+ (optional|arch=arm64)gcm_mulk_96l_arm64_pmull@Base 2.5.0
+ gcm_mulk_128b@Base 2.5.0
+ (optional|arch=i386 amd64)gcm_mulk_128b_x86ish_pclmul@Base 2.5.0
+ (optional|arch=i386 amd64)gcm_mulk_128b_x86ish_pclmul_avx@Base 2.5.0
+ (optional|arch=armel armhf)gcm_mulk_128b_arm_crypto@Base 2.5.0
+ (optional|arch=arm64)gcm_mulk_128b_arm64_pmull@Base 2.5.0
+ gcm_mulk_128l@Base 2.5.0
+ (optional|arch=i386 amd64)gcm_mulk_128l_x86ish_pclmul@Base 2.5.0
+ (optional|arch=i386 amd64)gcm_mulk_128l_x86ish_pclmul_avx@Base 2.5.0
+ (optional|arch=armel armhf)gcm_mulk_128l_arm_crypto@Base 2.5.0
+ (optional|arch=arm64)gcm_mulk_128l_arm64_pmull@Base 2.5.0
+ gcm_mulk_192b@Base 2.5.0
+ (optional|arch=i386 amd64)gcm_mulk_192b_x86ish_pclmul@Base 2.5.0
+ (optional|arch=i386 amd64)gcm_mulk_192b_x86ish_pclmul_avx@Base 2.5.0
+ (optional|arch=armel armhf)gcm_mulk_192b_arm_crypto@Base 2.5.0
+ (optional|arch=arm64)gcm_mulk_192b_arm64_pmull@Base 2.5.0
+ gcm_mulk_192l@Base 2.5.0
+ (optional|arch=i386 amd64)gcm_mulk_192l_x86ish_pclmul@Base 2.5.0
+ (optional|arch=i386 amd64)gcm_mulk_192l_x86ish_pclmul_avx@Base 2.5.0
+ (optional|arch=armel armhf)gcm_mulk_192l_arm_crypto@Base 2.5.0
+ (optional|arch=arm64)gcm_mulk_192l_arm64_pmull@Base 2.5.0
+ gcm_mulk_256b@Base 2.5.0
+ (optional|arch=i386 amd64)gcm_mulk_256b_x86ish_pclmul@Base 2.5.0
+ (optional|arch=i386 amd64)gcm_mulk_256b_x86ish_pclmul_avx@Base 2.5.0
+ (optional|arch=armel armhf)gcm_mulk_256b_arm_crypto@Base 2.5.0
+ (optional|arch=arm64)gcm_mulk_256b_arm64_pmull@Base 2.5.0
+ gcm_mulk_256l@Base 2.5.0
+ (optional|arch=i386 amd64)gcm_mulk_256l_x86ish_pclmul@Base 2.5.0
+ (optional|arch=i386 amd64)gcm_mulk_256l_x86ish_pclmul_avx@Base 2.5.0
+ (optional|arch=armel armhf)gcm_mulk_256l_arm_crypto@Base 2.5.0
+ (optional|arch=arm64)gcm_mulk_256l_arm64_pmull@Base 2.5.0
+
+## latinpoly
+ latinpoly_noncesz@Base 2.5.0
+ latinpoly_tagsz@Base 2.5.0
+ latinpoly_aadhash_naclbox@Base 2.5.0
+ latinpoly_aadhash_poly1305@Base 2.5.0
+ latinpoly_aaddestroy@Base 2.5.0
+ latinpoly_tag@Base 2.5.0
+
+## ocb
+ ocb_ctz@Base 2.5.0
+ ocb_ctzl@Base 2.5.0
+
## blowfish
blowfish_init@Base 2.0.0
blowfish_keysz@Base 2.0.0
blowfish_counterbdry@Base 2.0.0
blowfish_counter@Base 2.0.0
blowfish_counterrand@Base 2.0.0
+ blowfish_ccminit@Base 2.5.0
+ blowfish_ccmreinit@Base 2.5.0
+ blowfish_ccmnoncesz@Base 2.5.0
+ blowfish_ccmtagsz@Base 2.5.0
+ blowfish_ccmaadhash@Base 2.5.0
+ blowfish_ccmencrypt@Base 2.5.0
+ blowfish_ccmdecrypt@Base 2.5.0
+ blowfish_ccmencryptdone@Base 2.5.0
+ blowfish_ccmdecryptdone@Base 2.5.0
+ blowfish_ccm@Base 2.5.0
+ blowfish_eaxinit@Base 2.5.0
+ blowfish_eaxreinit@Base 2.5.0
+ blowfish_eaxsetkey@Base 2.5.0
+ blowfish_eaxnoncesz@Base 2.5.0
+ blowfish_eaxtagsz@Base 2.5.0
+ blowfish_eaxaadinit@Base 2.5.0
+ blowfish_eaxaadhash@Base 2.5.0
+ blowfish_eaxencrypt@Base 2.5.0
+ blowfish_eaxdecrypt@Base 2.5.0
+ blowfish_eaxencryptdone@Base 2.5.0
+ blowfish_eaxdecryptdone@Base 2.5.0
+ blowfish_eax@Base 2.5.0
+ blowfish_gcminit@Base 2.5.0
+ blowfish_gcmreinit@Base 2.5.0
+ blowfish_gcmsetkey@Base 2.5.0
+ blowfish_gcmnoncesz@Base 2.5.0
+ blowfish_gcmtagsz@Base 2.5.0
+ blowfish_gcmaadinit@Base 2.5.0
+ blowfish_gcmaadhash@Base 2.5.0
+ blowfish_gcmencrypt@Base 2.5.0
+ blowfish_gcmdecrypt@Base 2.5.0
+ blowfish_gcmencryptdone@Base 2.5.0
+ blowfish_gcmdecryptdone@Base 2.5.0
+ blowfish_gcm@Base 2.5.0
+ blowfish_ocb1init@Base 2.5.0
+ blowfish_ocb1reinit@Base 2.5.0
+ blowfish_ocb1setkey@Base 2.5.0
+ blowfish_ocb1policy@Base 2.5.0
+ blowfish_ocb1noncesz@Base 2.5.0
+ blowfish_ocb1tagsz@Base 2.5.0
+ blowfish_ocb1aadinit@Base 2.5.0
+ blowfish_ocb1aadhash@Base 2.5.0
+ blowfish_ocb1aadtag@Base 2.5.0
+ blowfish_ocb1encrypt@Base 2.5.0
+ blowfish_ocb1decrypt@Base 2.5.0
+ blowfish_ocb1encryptdone@Base 2.5.0
+ blowfish_ocb1decryptdone@Base 2.5.0
+ blowfish_ocb1@Base 2.5.0
+ blowfish_ocb3init@Base 2.5.0
+ blowfish_ocb3step@Base 2.5.0
+ blowfish_ocb3reinit@Base 2.5.0
+ blowfish_ocb3setkey@Base 2.5.0
+ blowfish_ocb3noncesz@Base 2.5.0
+ blowfish_ocb3aadinit@Base 2.5.0
+ blowfish_ocb3aadhash@Base 2.5.0
+ blowfish_ocb3encrypt@Base 2.5.0
+ blowfish_ocb3decrypt@Base 2.5.0
+ blowfish_ocb3encryptdone@Base 2.5.0
+ blowfish_ocb3decryptdone@Base 2.5.0
+ blowfish_ocb3tagsz@Base 2.5.0
+ blowfish_ocb3@Base 2.5.0
+ blowfish_omacmasks@Base 2.5.0
+ blowfish_omacpolicy@Base 2.5.0
+ blowfish_omacdone@Base 2.5.0
+ blowfish_cmacinit@Base 2.5.0
+ blowfish_cmacsetkey@Base 2.5.0
+ blowfish_cmachash@Base 2.5.0
+ blowfish_cmacdone@Base 2.5.0
+ blowfish_cmac@Base 2.5.0
+ blowfish_pmac1init@Base 2.5.0
+ blowfish_pmac1setkey@Base 2.5.0
+ blowfish_pmac1hash@Base 2.5.0
+ blowfish_pmac1done@Base 2.5.0
+ blowfish_pmac1@Base 2.5.0
## cast128
cast128_init@Base 2.0.0
cast128_counterbdry@Base 2.0.0
cast128_counter@Base 2.0.0
cast128_counterrand@Base 2.0.0
+ cast128_ccminit@Base 2.5.0
+ cast128_ccmreinit@Base 2.5.0
+ cast128_ccmnoncesz@Base 2.5.0
+ cast128_ccmtagsz@Base 2.5.0
+ cast128_ccmaadhash@Base 2.5.0
+ cast128_ccmencrypt@Base 2.5.0
+ cast128_ccmdecrypt@Base 2.5.0
+ cast128_ccmencryptdone@Base 2.5.0
+ cast128_ccmdecryptdone@Base 2.5.0
+ cast128_ccm@Base 2.5.0
+ cast128_eaxinit@Base 2.5.0
+ cast128_eaxreinit@Base 2.5.0
+ cast128_eaxsetkey@Base 2.5.0
+ cast128_eaxnoncesz@Base 2.5.0
+ cast128_eaxtagsz@Base 2.5.0
+ cast128_eaxaadinit@Base 2.5.0
+ cast128_eaxaadhash@Base 2.5.0
+ cast128_eaxencrypt@Base 2.5.0
+ cast128_eaxdecrypt@Base 2.5.0
+ cast128_eaxencryptdone@Base 2.5.0
+ cast128_eaxdecryptdone@Base 2.5.0
+ cast128_eax@Base 2.5.0
+ cast128_gcminit@Base 2.5.0
+ cast128_gcmreinit@Base 2.5.0
+ cast128_gcmsetkey@Base 2.5.0
+ cast128_gcmnoncesz@Base 2.5.0
+ cast128_gcmtagsz@Base 2.5.0
+ cast128_gcmaadinit@Base 2.5.0
+ cast128_gcmaadhash@Base 2.5.0
+ cast128_gcmencrypt@Base 2.5.0
+ cast128_gcmdecrypt@Base 2.5.0
+ cast128_gcmencryptdone@Base 2.5.0
+ cast128_gcmdecryptdone@Base 2.5.0
+ cast128_gcm@Base 2.5.0
+ cast128_ocb1init@Base 2.5.0
+ cast128_ocb1reinit@Base 2.5.0
+ cast128_ocb1setkey@Base 2.5.0
+ cast128_ocb1policy@Base 2.5.0
+ cast128_ocb1noncesz@Base 2.5.0
+ cast128_ocb1tagsz@Base 2.5.0
+ cast128_ocb1aadinit@Base 2.5.0
+ cast128_ocb1aadhash@Base 2.5.0
+ cast128_ocb1aadtag@Base 2.5.0
+ cast128_ocb1encrypt@Base 2.5.0
+ cast128_ocb1decrypt@Base 2.5.0
+ cast128_ocb1encryptdone@Base 2.5.0
+ cast128_ocb1decryptdone@Base 2.5.0
+ cast128_ocb1@Base 2.5.0
+ cast128_ocb3init@Base 2.5.0
+ cast128_ocb3step@Base 2.5.0
+ cast128_ocb3reinit@Base 2.5.0
+ cast128_ocb3setkey@Base 2.5.0
+ cast128_ocb3noncesz@Base 2.5.0
+ cast128_ocb3aadinit@Base 2.5.0
+ cast128_ocb3aadhash@Base 2.5.0
+ cast128_ocb3encrypt@Base 2.5.0
+ cast128_ocb3decrypt@Base 2.5.0
+ cast128_ocb3encryptdone@Base 2.5.0
+ cast128_ocb3decryptdone@Base 2.5.0
+ cast128_ocb3tagsz@Base 2.5.0
+ cast128_ocb3@Base 2.5.0
+ cast128_omacmasks@Base 2.5.0
+ cast128_omacpolicy@Base 2.5.0
+ cast128_omacdone@Base 2.5.0
+ cast128_cmacinit@Base 2.5.0
+ cast128_cmacsetkey@Base 2.5.0
+ cast128_cmachash@Base 2.5.0
+ cast128_cmacdone@Base 2.5.0
+ cast128_cmac@Base 2.5.0
+ cast128_pmac1init@Base 2.5.0
+ cast128_pmac1setkey@Base 2.5.0
+ cast128_pmac1hash@Base 2.5.0
+ cast128_pmac1done@Base 2.5.0
+ cast128_pmac1@Base 2.5.0
## cast256
cast256_init@Base 2.0.0
cast256_counterbdry@Base 2.0.0
cast256_counter@Base 2.0.0
cast256_counterrand@Base 2.0.0
+ cast256_ccminit@Base 2.5.0
+ cast256_ccmreinit@Base 2.5.0
+ cast256_ccmnoncesz@Base 2.5.0
+ cast256_ccmtagsz@Base 2.5.0
+ cast256_ccmaadhash@Base 2.5.0
+ cast256_ccmencrypt@Base 2.5.0
+ cast256_ccmdecrypt@Base 2.5.0
+ cast256_ccmencryptdone@Base 2.5.0
+ cast256_ccmdecryptdone@Base 2.5.0
+ cast256_ccm@Base 2.5.0
+ cast256_eaxinit@Base 2.5.0
+ cast256_eaxreinit@Base 2.5.0
+ cast256_eaxsetkey@Base 2.5.0
+ cast256_eaxnoncesz@Base 2.5.0
+ cast256_eaxtagsz@Base 2.5.0
+ cast256_eaxaadinit@Base 2.5.0
+ cast256_eaxaadhash@Base 2.5.0
+ cast256_eaxencrypt@Base 2.5.0
+ cast256_eaxdecrypt@Base 2.5.0
+ cast256_eaxencryptdone@Base 2.5.0
+ cast256_eaxdecryptdone@Base 2.5.0
+ cast256_eax@Base 2.5.0
+ cast256_gcminit@Base 2.5.0
+ cast256_gcmreinit@Base 2.5.0
+ cast256_gcmsetkey@Base 2.5.0
+ cast256_gcmnoncesz@Base 2.5.0
+ cast256_gcmtagsz@Base 2.5.0
+ cast256_gcmaadinit@Base 2.5.0
+ cast256_gcmaadhash@Base 2.5.0
+ cast256_gcmencrypt@Base 2.5.0
+ cast256_gcmdecrypt@Base 2.5.0
+ cast256_gcmencryptdone@Base 2.5.0
+ cast256_gcmdecryptdone@Base 2.5.0
+ cast256_gcm@Base 2.5.0
+ cast256_ocb1init@Base 2.5.0
+ cast256_ocb1reinit@Base 2.5.0
+ cast256_ocb1setkey@Base 2.5.0
+ cast256_ocb1policy@Base 2.5.0
+ cast256_ocb1noncesz@Base 2.5.0
+ cast256_ocb1tagsz@Base 2.5.0
+ cast256_ocb1aadinit@Base 2.5.0
+ cast256_ocb1aadhash@Base 2.5.0
+ cast256_ocb1aadtag@Base 2.5.0
+ cast256_ocb1encrypt@Base 2.5.0
+ cast256_ocb1decrypt@Base 2.5.0
+ cast256_ocb1encryptdone@Base 2.5.0
+ cast256_ocb1decryptdone@Base 2.5.0
+ cast256_ocb1@Base 2.5.0
+ cast256_ocb3init@Base 2.5.0
+ cast256_ocb3step@Base 2.5.0
+ cast256_ocb3reinit@Base 2.5.0
+ cast256_ocb3setkey@Base 2.5.0
+ cast256_ocb3noncesz@Base 2.5.0
+ cast256_ocb3aadinit@Base 2.5.0
+ cast256_ocb3aadhash@Base 2.5.0
+ cast256_ocb3encrypt@Base 2.5.0
+ cast256_ocb3decrypt@Base 2.5.0
+ cast256_ocb3encryptdone@Base 2.5.0
+ cast256_ocb3decryptdone@Base 2.5.0
+ cast256_ocb3tagsz@Base 2.5.0
+ cast256_ocb3@Base 2.5.0
+ cast256_omacmasks@Base 2.5.0
+ cast256_omacpolicy@Base 2.5.0
+ cast256_omacdone@Base 2.5.0
+ cast256_cmacinit@Base 2.5.0
+ cast256_cmacsetkey@Base 2.5.0
+ cast256_cmachash@Base 2.5.0
+ cast256_cmacdone@Base 2.5.0
+ cast256_cmac@Base 2.5.0
+ cast256_pmac1init@Base 2.5.0
+ cast256_pmac1setkey@Base 2.5.0
+ cast256_pmac1hash@Base 2.5.0
+ cast256_pmac1done@Base 2.5.0
+ cast256_pmac1@Base 2.5.0
## chacha
chacha_init@Base 2.2.0
chacha12_encrypt@Base 2.2.0
chacha20_encrypt@Base 2.2.0
(optional|arch=i386 amd64)chacha_core_x86ish_sse2@Base 2.3.0
+ (optional|arch=i386 amd64)chacha_core_x86ish_avx@Base 2.3.0
(optional|arch=armel armhf)chacha_core_arm_neon@Base 2.3.0
(optional|arch=arm64)chacha_core_arm64@Base 2.4.3
chacha8@Base 2.2.0
chacha8_ietf_rand@Base 2.4.2
chacha12_ietf_rand@Base 2.4.2
chacha20_ietf_rand@Base 2.4.2
+ chacha8_naclbox@Base 2.5.0
+ chacha12_naclbox@Base 2.5.0
+ chacha20_naclbox@Base 2.5.0
+ chacha8_poly1305@Base 2.5.0
+ chacha12_poly1305@Base 2.5.0
+ chacha20_poly1305@Base 2.5.0
hchacha12_prf@Base 2.2.0
hchacha20_prf@Base 2.2.0
hchacha8_prf@Base 2.2.0
des_counterbdry@Base 2.0.0
des_counter@Base 2.0.0
des_counterrand@Base 2.0.0
+ des_ccminit@Base 2.5.0
+ des_ccmreinit@Base 2.5.0
+ des_ccmnoncesz@Base 2.5.0
+ des_ccmtagsz@Base 2.5.0
+ des_ccmaadhash@Base 2.5.0
+ des_ccmencrypt@Base 2.5.0
+ des_ccmdecrypt@Base 2.5.0
+ des_ccmencryptdone@Base 2.5.0
+ des_ccmdecryptdone@Base 2.5.0
+ des_ccm@Base 2.5.0
+ des_eaxinit@Base 2.5.0
+ des_eaxreinit@Base 2.5.0
+ des_eaxsetkey@Base 2.5.0
+ des_eaxnoncesz@Base 2.5.0
+ des_eaxtagsz@Base 2.5.0
+ des_eaxaadinit@Base 2.5.0
+ des_eaxaadhash@Base 2.5.0
+ des_eaxencrypt@Base 2.5.0
+ des_eaxdecrypt@Base 2.5.0
+ des_eaxencryptdone@Base 2.5.0
+ des_eaxdecryptdone@Base 2.5.0
+ des_eax@Base 2.5.0
+ des_gcminit@Base 2.5.0
+ des_gcmreinit@Base 2.5.0
+ des_gcmsetkey@Base 2.5.0
+ des_gcmnoncesz@Base 2.5.0
+ des_gcmtagsz@Base 2.5.0
+ des_gcmaadinit@Base 2.5.0
+ des_gcmaadhash@Base 2.5.0
+ des_gcmencrypt@Base 2.5.0
+ des_gcmdecrypt@Base 2.5.0
+ des_gcmencryptdone@Base 2.5.0
+ des_gcmdecryptdone@Base 2.5.0
+ des_gcm@Base 2.5.0
+ des_ocb1init@Base 2.5.0
+ des_ocb1reinit@Base 2.5.0
+ des_ocb1setkey@Base 2.5.0
+ des_ocb1policy@Base 2.5.0
+ des_ocb1noncesz@Base 2.5.0
+ des_ocb1tagsz@Base 2.5.0
+ des_ocb1aadinit@Base 2.5.0
+ des_ocb1aadhash@Base 2.5.0
+ des_ocb1aadtag@Base 2.5.0
+ des_ocb1encrypt@Base 2.5.0
+ des_ocb1decrypt@Base 2.5.0
+ des_ocb1encryptdone@Base 2.5.0
+ des_ocb1decryptdone@Base 2.5.0
+ des_ocb1@Base 2.5.0
+ des_ocb3init@Base 2.5.0
+ des_ocb3step@Base 2.5.0
+ des_ocb3reinit@Base 2.5.0
+ des_ocb3setkey@Base 2.5.0
+ des_ocb3noncesz@Base 2.5.0
+ des_ocb3aadinit@Base 2.5.0
+ des_ocb3aadhash@Base 2.5.0
+ des_ocb3encrypt@Base 2.5.0
+ des_ocb3decrypt@Base 2.5.0
+ des_ocb3encryptdone@Base 2.5.0
+ des_ocb3decryptdone@Base 2.5.0
+ des_ocb3tagsz@Base 2.5.0
+ des_ocb3@Base 2.5.0
+ des_omacmasks@Base 2.5.0
+ des_omacpolicy@Base 2.5.0
+ des_omacdone@Base 2.5.0
+ des_cmacinit@Base 2.5.0
+ des_cmacsetkey@Base 2.5.0
+ des_cmachash@Base 2.5.0
+ des_cmacdone@Base 2.5.0
+ des_cmac@Base 2.5.0
+ des_pmac1init@Base 2.5.0
+ des_pmac1setkey@Base 2.5.0
+ des_pmac1hash@Base 2.5.0
+ des_pmac1done@Base 2.5.0
+ des_pmac1@Base 2.5.0
## des3
des3_init@Base 2.0.0
des3_counterbdry@Base 2.0.0
des3_counter@Base 2.0.0
des3_counterrand@Base 2.0.0
+ des3_ccminit@Base 2.5.0
+ des3_ccmreinit@Base 2.5.0
+ des3_ccmnoncesz@Base 2.5.0
+ des3_ccmtagsz@Base 2.5.0
+ des3_ccmaadhash@Base 2.5.0
+ des3_ccmencrypt@Base 2.5.0
+ des3_ccmdecrypt@Base 2.5.0
+ des3_ccmencryptdone@Base 2.5.0
+ des3_ccmdecryptdone@Base 2.5.0
+ des3_ccm@Base 2.5.0
+ des3_eaxinit@Base 2.5.0
+ des3_eaxreinit@Base 2.5.0
+ des3_eaxsetkey@Base 2.5.0
+ des3_eaxnoncesz@Base 2.5.0
+ des3_eaxtagsz@Base 2.5.0
+ des3_eaxaadinit@Base 2.5.0
+ des3_eaxaadhash@Base 2.5.0
+ des3_eaxencrypt@Base 2.5.0
+ des3_eaxdecrypt@Base 2.5.0
+ des3_eaxencryptdone@Base 2.5.0
+ des3_eaxdecryptdone@Base 2.5.0
+ des3_eax@Base 2.5.0
+ des3_gcminit@Base 2.5.0
+ des3_gcmreinit@Base 2.5.0
+ des3_gcmsetkey@Base 2.5.0
+ des3_gcmnoncesz@Base 2.5.0
+ des3_gcmtagsz@Base 2.5.0
+ des3_gcmaadinit@Base 2.5.0
+ des3_gcmaadhash@Base 2.5.0
+ des3_gcmencrypt@Base 2.5.0
+ des3_gcmdecrypt@Base 2.5.0
+ des3_gcmencryptdone@Base 2.5.0
+ des3_gcmdecryptdone@Base 2.5.0
+ des3_gcm@Base 2.5.0
+ des3_ocb1init@Base 2.5.0
+ des3_ocb1reinit@Base 2.5.0
+ des3_ocb1setkey@Base 2.5.0
+ des3_ocb1policy@Base 2.5.0
+ des3_ocb1noncesz@Base 2.5.0
+ des3_ocb1tagsz@Base 2.5.0
+ des3_ocb1aadinit@Base 2.5.0
+ des3_ocb1aadhash@Base 2.5.0
+ des3_ocb1aadtag@Base 2.5.0
+ des3_ocb1encrypt@Base 2.5.0
+ des3_ocb1decrypt@Base 2.5.0
+ des3_ocb1encryptdone@Base 2.5.0
+ des3_ocb1decryptdone@Base 2.5.0
+ des3_ocb1@Base 2.5.0
+ des3_ocb3init@Base 2.5.0
+ des3_ocb3step@Base 2.5.0
+ des3_ocb3reinit@Base 2.5.0
+ des3_ocb3setkey@Base 2.5.0
+ des3_ocb3noncesz@Base 2.5.0
+ des3_ocb3aadinit@Base 2.5.0
+ des3_ocb3aadhash@Base 2.5.0
+ des3_ocb3encrypt@Base 2.5.0
+ des3_ocb3decrypt@Base 2.5.0
+ des3_ocb3encryptdone@Base 2.5.0
+ des3_ocb3decryptdone@Base 2.5.0
+ des3_ocb3tagsz@Base 2.5.0
+ des3_ocb3@Base 2.5.0
+ des3_omacmasks@Base 2.5.0
+ des3_omacpolicy@Base 2.5.0
+ des3_omacdone@Base 2.5.0
+ des3_cmacinit@Base 2.5.0
+ des3_cmacsetkey@Base 2.5.0
+ des3_cmachash@Base 2.5.0
+ des3_cmacdone@Base 2.5.0
+ des3_cmac@Base 2.5.0
+ des3_pmac1init@Base 2.5.0
+ des3_pmac1setkey@Base 2.5.0
+ des3_pmac1hash@Base 2.5.0
+ des3_pmac1done@Base 2.5.0
+ des3_pmac1@Base 2.5.0
## desx
desx_init@Base 2.0.0
desx_counterbdry@Base 2.0.0
desx_counter@Base 2.0.0
desx_counterrand@Base 2.0.0
+ desx_ccminit@Base 2.5.0
+ desx_ccmreinit@Base 2.5.0
+ desx_ccmnoncesz@Base 2.5.0
+ desx_ccmtagsz@Base 2.5.0
+ desx_ccmaadhash@Base 2.5.0
+ desx_ccmencrypt@Base 2.5.0
+ desx_ccmdecrypt@Base 2.5.0
+ desx_ccmencryptdone@Base 2.5.0
+ desx_ccmdecryptdone@Base 2.5.0
+ desx_ccm@Base 2.5.0
+ desx_eaxinit@Base 2.5.0
+ desx_eaxreinit@Base 2.5.0
+ desx_eaxsetkey@Base 2.5.0
+ desx_eaxnoncesz@Base 2.5.0
+ desx_eaxtagsz@Base 2.5.0
+ desx_eaxaadinit@Base 2.5.0
+ desx_eaxaadhash@Base 2.5.0
+ desx_eaxencrypt@Base 2.5.0
+ desx_eaxdecrypt@Base 2.5.0
+ desx_eaxencryptdone@Base 2.5.0
+ desx_eaxdecryptdone@Base 2.5.0
+ desx_eax@Base 2.5.0
+ desx_gcminit@Base 2.5.0
+ desx_gcmreinit@Base 2.5.0
+ desx_gcmsetkey@Base 2.5.0
+ desx_gcmnoncesz@Base 2.5.0
+ desx_gcmtagsz@Base 2.5.0
+ desx_gcmaadinit@Base 2.5.0
+ desx_gcmaadhash@Base 2.5.0
+ desx_gcmencrypt@Base 2.5.0
+ desx_gcmdecrypt@Base 2.5.0
+ desx_gcmencryptdone@Base 2.5.0
+ desx_gcmdecryptdone@Base 2.5.0
+ desx_gcm@Base 2.5.0
+ desx_ocb1init@Base 2.5.0
+ desx_ocb1reinit@Base 2.5.0
+ desx_ocb1setkey@Base 2.5.0
+ desx_ocb1policy@Base 2.5.0
+ desx_ocb1noncesz@Base 2.5.0
+ desx_ocb1tagsz@Base 2.5.0
+ desx_ocb1aadinit@Base 2.5.0
+ desx_ocb1aadhash@Base 2.5.0
+ desx_ocb1aadtag@Base 2.5.0
+ desx_ocb1encrypt@Base 2.5.0
+ desx_ocb1decrypt@Base 2.5.0
+ desx_ocb1encryptdone@Base 2.5.0
+ desx_ocb1decryptdone@Base 2.5.0
+ desx_ocb1@Base 2.5.0
+ desx_ocb3init@Base 2.5.0
+ desx_ocb3step@Base 2.5.0
+ desx_ocb3reinit@Base 2.5.0
+ desx_ocb3setkey@Base 2.5.0
+ desx_ocb3noncesz@Base 2.5.0
+ desx_ocb3aadinit@Base 2.5.0
+ desx_ocb3aadhash@Base 2.5.0
+ desx_ocb3encrypt@Base 2.5.0
+ desx_ocb3decrypt@Base 2.5.0
+ desx_ocb3encryptdone@Base 2.5.0
+ desx_ocb3decryptdone@Base 2.5.0
+ desx_ocb3tagsz@Base 2.5.0
+ desx_ocb3@Base 2.5.0
+ desx_omacmasks@Base 2.5.0
+ desx_omacpolicy@Base 2.5.0
+ desx_omacdone@Base 2.5.0
+ desx_cmacinit@Base 2.5.0
+ desx_cmacsetkey@Base 2.5.0
+ desx_cmachash@Base 2.5.0
+ desx_cmacdone@Base 2.5.0
+ desx_cmac@Base 2.5.0
+ desx_pmac1init@Base 2.5.0
+ desx_pmac1setkey@Base 2.5.0
+ desx_pmac1hash@Base 2.5.0
+ desx_pmac1done@Base 2.5.0
+ desx_pmac1@Base 2.5.0
## idea
idea_init@Base 2.0.0
idea_counterbdry@Base 2.0.0
idea_counter@Base 2.4.3
idea_counterrand@Base 2.0.0
+ idea_ccminit@Base 2.5.0
+ idea_ccmreinit@Base 2.5.0
+ idea_ccmnoncesz@Base 2.5.0
+ idea_ccmtagsz@Base 2.5.0
+ idea_ccmaadhash@Base 2.5.0
+ idea_ccmencrypt@Base 2.5.0
+ idea_ccmdecrypt@Base 2.5.0
+ idea_ccmencryptdone@Base 2.5.0
+ idea_ccmdecryptdone@Base 2.5.0
+ idea_ccm@Base 2.5.0
+ idea_eaxinit@Base 2.5.0
+ idea_eaxreinit@Base 2.5.0
+ idea_eaxsetkey@Base 2.5.0
+ idea_eaxnoncesz@Base 2.5.0
+ idea_eaxtagsz@Base 2.5.0
+ idea_eaxaadinit@Base 2.5.0
+ idea_eaxaadhash@Base 2.5.0
+ idea_eaxencrypt@Base 2.5.0
+ idea_eaxdecrypt@Base 2.5.0
+ idea_eaxencryptdone@Base 2.5.0
+ idea_eaxdecryptdone@Base 2.5.0
+ idea_eax@Base 2.5.0
+ idea_gcminit@Base 2.5.0
+ idea_gcmreinit@Base 2.5.0
+ idea_gcmsetkey@Base 2.5.0
+ idea_gcmnoncesz@Base 2.5.0
+ idea_gcmtagsz@Base 2.5.0
+ idea_gcmaadinit@Base 2.5.0
+ idea_gcmaadhash@Base 2.5.0
+ idea_gcmencrypt@Base 2.5.0
+ idea_gcmdecrypt@Base 2.5.0
+ idea_gcmencryptdone@Base 2.5.0
+ idea_gcmdecryptdone@Base 2.5.0
+ idea_gcm@Base 2.5.0
+ idea_ocb1init@Base 2.5.0
+ idea_ocb1reinit@Base 2.5.0
+ idea_ocb1setkey@Base 2.5.0
+ idea_ocb1policy@Base 2.5.0
+ idea_ocb1noncesz@Base 2.5.0
+ idea_ocb1tagsz@Base 2.5.0
+ idea_ocb1aadinit@Base 2.5.0
+ idea_ocb1aadhash@Base 2.5.0
+ idea_ocb1aadtag@Base 2.5.0
+ idea_ocb1encrypt@Base 2.5.0
+ idea_ocb1decrypt@Base 2.5.0
+ idea_ocb1encryptdone@Base 2.5.0
+ idea_ocb1decryptdone@Base 2.5.0
+ idea_ocb1@Base 2.5.0
+ idea_ocb3init@Base 2.5.0
+ idea_ocb3step@Base 2.5.0
+ idea_ocb3reinit@Base 2.5.0
+ idea_ocb3setkey@Base 2.5.0
+ idea_ocb3noncesz@Base 2.5.0
+ idea_ocb3aadinit@Base 2.5.0
+ idea_ocb3aadhash@Base 2.5.0
+ idea_ocb3encrypt@Base 2.5.0
+ idea_ocb3decrypt@Base 2.5.0
+ idea_ocb3encryptdone@Base 2.5.0
+ idea_ocb3decryptdone@Base 2.5.0
+ idea_ocb3tagsz@Base 2.5.0
+ idea_ocb3@Base 2.5.0
+ idea_omacmasks@Base 2.5.0
+ idea_omacpolicy@Base 2.5.0
+ idea_omacdone@Base 2.5.0
+ idea_cmacinit@Base 2.5.0
+ idea_cmacsetkey@Base 2.5.0
+ idea_cmachash@Base 2.5.0
+ idea_cmacdone@Base 2.5.0
+ idea_cmac@Base 2.5.0
+ idea_pmac1init@Base 2.5.0
+ idea_pmac1setkey@Base 2.5.0
+ idea_pmac1hash@Base 2.5.0
+ idea_pmac1done@Base 2.5.0
+ idea_pmac1@Base 2.5.0
## mars
mars_init@Base 2.0.0
mars_counterbdry@Base 2.0.0
mars_counter@Base 2.0.0
mars_counterrand@Base 2.0.0
+ mars_ccminit@Base 2.5.0
+ mars_ccmreinit@Base 2.5.0
+ mars_ccmnoncesz@Base 2.5.0
+ mars_ccmtagsz@Base 2.5.0
+ mars_ccmaadhash@Base 2.5.0
+ mars_ccmencrypt@Base 2.5.0
+ mars_ccmdecrypt@Base 2.5.0
+ mars_ccmencryptdone@Base 2.5.0
+ mars_ccmdecryptdone@Base 2.5.0
+ mars_ccm@Base 2.5.0
+ mars_eaxinit@Base 2.5.0
+ mars_eaxreinit@Base 2.5.0
+ mars_eaxsetkey@Base 2.5.0
+ mars_eaxnoncesz@Base 2.5.0
+ mars_eaxtagsz@Base 2.5.0
+ mars_eaxaadinit@Base 2.5.0
+ mars_eaxaadhash@Base 2.5.0
+ mars_eaxencrypt@Base 2.5.0
+ mars_eaxdecrypt@Base 2.5.0
+ mars_eaxencryptdone@Base 2.5.0
+ mars_eaxdecryptdone@Base 2.5.0
+ mars_eax@Base 2.5.0
+ mars_gcminit@Base 2.5.0
+ mars_gcmreinit@Base 2.5.0
+ mars_gcmsetkey@Base 2.5.0
+ mars_gcmnoncesz@Base 2.5.0
+ mars_gcmtagsz@Base 2.5.0
+ mars_gcmaadinit@Base 2.5.0
+ mars_gcmaadhash@Base 2.5.0
+ mars_gcmencrypt@Base 2.5.0
+ mars_gcmdecrypt@Base 2.5.0
+ mars_gcmencryptdone@Base 2.5.0
+ mars_gcmdecryptdone@Base 2.5.0
+ mars_gcm@Base 2.5.0
+ mars_ocb1init@Base 2.5.0
+ mars_ocb1reinit@Base 2.5.0
+ mars_ocb1setkey@Base 2.5.0
+ mars_ocb1policy@Base 2.5.0
+ mars_ocb1noncesz@Base 2.5.0
+ mars_ocb1tagsz@Base 2.5.0
+ mars_ocb1aadinit@Base 2.5.0
+ mars_ocb1aadhash@Base 2.5.0
+ mars_ocb1aadtag@Base 2.5.0
+ mars_ocb1encrypt@Base 2.5.0
+ mars_ocb1decrypt@Base 2.5.0
+ mars_ocb1encryptdone@Base 2.5.0
+ mars_ocb1decryptdone@Base 2.5.0
+ mars_ocb1@Base 2.5.0
+ mars_ocb3init@Base 2.5.0
+ mars_ocb3step@Base 2.5.0
+ mars_ocb3reinit@Base 2.5.0
+ mars_ocb3setkey@Base 2.5.0
+ mars_ocb3noncesz@Base 2.5.0
+ mars_ocb3aadinit@Base 2.5.0
+ mars_ocb3aadhash@Base 2.5.0
+ mars_ocb3encrypt@Base 2.5.0
+ mars_ocb3decrypt@Base 2.5.0
+ mars_ocb3encryptdone@Base 2.5.0
+ mars_ocb3decryptdone@Base 2.5.0
+ mars_ocb3tagsz@Base 2.5.0
+ mars_ocb3@Base 2.5.0
+ mars_omacmasks@Base 2.5.0
+ mars_omacpolicy@Base 2.5.0
+ mars_omacdone@Base 2.5.0
+ mars_cmacinit@Base 2.5.0
+ mars_cmacsetkey@Base 2.5.0
+ mars_cmachash@Base 2.5.0
+ mars_cmacdone@Base 2.5.0
+ mars_cmac@Base 2.5.0
+ mars_pmac1init@Base 2.5.0
+ mars_pmac1setkey@Base 2.5.0
+ mars_pmac1hash@Base 2.5.0
+ mars_pmac1done@Base 2.5.0
+ mars_pmac1@Base 2.5.0
## noekeon
noekeon_init@Base 2.0.0
noekeon_counterbdry@Base 2.0.0
noekeon_counter@Base 2.0.0
noekeon_counterrand@Base 2.0.0
+ noekeon_ccminit@Base 2.5.0
+ noekeon_ccmreinit@Base 2.5.0
+ noekeon_ccmnoncesz@Base 2.5.0
+ noekeon_ccmtagsz@Base 2.5.0
+ noekeon_ccmaadhash@Base 2.5.0
+ noekeon_ccmencrypt@Base 2.5.0
+ noekeon_ccmdecrypt@Base 2.5.0
+ noekeon_ccmencryptdone@Base 2.5.0
+ noekeon_ccmdecryptdone@Base 2.5.0
+ noekeon_ccm@Base 2.5.0
+ noekeon_eaxinit@Base 2.5.0
+ noekeon_eaxreinit@Base 2.5.0
+ noekeon_eaxsetkey@Base 2.5.0
+ noekeon_eaxnoncesz@Base 2.5.0
+ noekeon_eaxtagsz@Base 2.5.0
+ noekeon_eaxaadinit@Base 2.5.0
+ noekeon_eaxaadhash@Base 2.5.0
+ noekeon_eaxencrypt@Base 2.5.0
+ noekeon_eaxdecrypt@Base 2.5.0
+ noekeon_eaxencryptdone@Base 2.5.0
+ noekeon_eaxdecryptdone@Base 2.5.0
+ noekeon_eax@Base 2.5.0
+ noekeon_gcminit@Base 2.5.0
+ noekeon_gcmreinit@Base 2.5.0
+ noekeon_gcmsetkey@Base 2.5.0
+ noekeon_gcmnoncesz@Base 2.5.0
+ noekeon_gcmtagsz@Base 2.5.0
+ noekeon_gcmaadinit@Base 2.5.0
+ noekeon_gcmaadhash@Base 2.5.0
+ noekeon_gcmencrypt@Base 2.5.0
+ noekeon_gcmdecrypt@Base 2.5.0
+ noekeon_gcmencryptdone@Base 2.5.0
+ noekeon_gcmdecryptdone@Base 2.5.0
+ noekeon_gcm@Base 2.5.0
+ noekeon_ocb1init@Base 2.5.0
+ noekeon_ocb1reinit@Base 2.5.0
+ noekeon_ocb1setkey@Base 2.5.0
+ noekeon_ocb1policy@Base 2.5.0
+ noekeon_ocb1noncesz@Base 2.5.0
+ noekeon_ocb1tagsz@Base 2.5.0
+ noekeon_ocb1aadinit@Base 2.5.0
+ noekeon_ocb1aadhash@Base 2.5.0
+ noekeon_ocb1aadtag@Base 2.5.0
+ noekeon_ocb1encrypt@Base 2.5.0
+ noekeon_ocb1decrypt@Base 2.5.0
+ noekeon_ocb1encryptdone@Base 2.5.0
+ noekeon_ocb1decryptdone@Base 2.5.0
+ noekeon_ocb1@Base 2.5.0
+ noekeon_ocb3init@Base 2.5.0
+ noekeon_ocb3step@Base 2.5.0
+ noekeon_ocb3reinit@Base 2.5.0
+ noekeon_ocb3setkey@Base 2.5.0
+ noekeon_ocb3noncesz@Base 2.5.0
+ noekeon_ocb3aadinit@Base 2.5.0
+ noekeon_ocb3aadhash@Base 2.5.0
+ noekeon_ocb3encrypt@Base 2.5.0
+ noekeon_ocb3decrypt@Base 2.5.0
+ noekeon_ocb3encryptdone@Base 2.5.0
+ noekeon_ocb3decryptdone@Base 2.5.0
+ noekeon_ocb3tagsz@Base 2.5.0
+ noekeon_ocb3@Base 2.5.0
+ noekeon_omacmasks@Base 2.5.0
+ noekeon_omacpolicy@Base 2.5.0
+ noekeon_omacdone@Base 2.5.0
+ noekeon_cmacinit@Base 2.5.0
+ noekeon_cmacsetkey@Base 2.5.0
+ noekeon_cmachash@Base 2.5.0
+ noekeon_cmacdone@Base 2.5.0
+ noekeon_cmac@Base 2.5.0
+ noekeon_pmac1init@Base 2.5.0
+ noekeon_pmac1setkey@Base 2.5.0
+ noekeon_pmac1hash@Base 2.5.0
+ noekeon_pmac1done@Base 2.5.0
+ noekeon_pmac1@Base 2.5.0
## rc2
rc2_init@Base 2.0.0
rc2_counterbdry@Base 2.0.0
rc2_counter@Base 2.0.0
rc2_counterrand@Base 2.0.0
+ rc2_ccminit@Base 2.5.0
+ rc2_ccmreinit@Base 2.5.0
+ rc2_ccmnoncesz@Base 2.5.0
+ rc2_ccmtagsz@Base 2.5.0
+ rc2_ccmaadhash@Base 2.5.0
+ rc2_ccmencrypt@Base 2.5.0
+ rc2_ccmdecrypt@Base 2.5.0
+ rc2_ccmencryptdone@Base 2.5.0
+ rc2_ccmdecryptdone@Base 2.5.0
+ rc2_ccm@Base 2.5.0
+ rc2_eaxinit@Base 2.5.0
+ rc2_eaxreinit@Base 2.5.0
+ rc2_eaxsetkey@Base 2.5.0
+ rc2_eaxnoncesz@Base 2.5.0
+ rc2_eaxtagsz@Base 2.5.0
+ rc2_eaxaadinit@Base 2.5.0
+ rc2_eaxaadhash@Base 2.5.0
+ rc2_eaxencrypt@Base 2.5.0
+ rc2_eaxdecrypt@Base 2.5.0
+ rc2_eaxencryptdone@Base 2.5.0
+ rc2_eaxdecryptdone@Base 2.5.0
+ rc2_eax@Base 2.5.0
+ rc2_gcminit@Base 2.5.0
+ rc2_gcmreinit@Base 2.5.0
+ rc2_gcmsetkey@Base 2.5.0
+ rc2_gcmnoncesz@Base 2.5.0
+ rc2_gcmtagsz@Base 2.5.0
+ rc2_gcmaadinit@Base 2.5.0
+ rc2_gcmaadhash@Base 2.5.0
+ rc2_gcmencrypt@Base 2.5.0
+ rc2_gcmdecrypt@Base 2.5.0
+ rc2_gcmencryptdone@Base 2.5.0
+ rc2_gcmdecryptdone@Base 2.5.0
+ rc2_gcm@Base 2.5.0
+ rc2_ocb1init@Base 2.5.0
+ rc2_ocb1reinit@Base 2.5.0
+ rc2_ocb1setkey@Base 2.5.0
+ rc2_ocb1policy@Base 2.5.0
+ rc2_ocb1noncesz@Base 2.5.0
+ rc2_ocb1tagsz@Base 2.5.0
+ rc2_ocb1aadinit@Base 2.5.0
+ rc2_ocb1aadhash@Base 2.5.0
+ rc2_ocb1aadtag@Base 2.5.0
+ rc2_ocb1encrypt@Base 2.5.0
+ rc2_ocb1decrypt@Base 2.5.0
+ rc2_ocb1encryptdone@Base 2.5.0
+ rc2_ocb1decryptdone@Base 2.5.0
+ rc2_ocb1@Base 2.5.0
+ rc2_ocb3init@Base 2.5.0
+ rc2_ocb3step@Base 2.5.0
+ rc2_ocb3reinit@Base 2.5.0
+ rc2_ocb3setkey@Base 2.5.0
+ rc2_ocb3noncesz@Base 2.5.0
+ rc2_ocb3aadinit@Base 2.5.0
+ rc2_ocb3aadhash@Base 2.5.0
+ rc2_ocb3encrypt@Base 2.5.0
+ rc2_ocb3decrypt@Base 2.5.0
+ rc2_ocb3encryptdone@Base 2.5.0
+ rc2_ocb3decryptdone@Base 2.5.0
+ rc2_ocb3tagsz@Base 2.5.0
+ rc2_ocb3@Base 2.5.0
+ rc2_omacmasks@Base 2.5.0
+ rc2_omacpolicy@Base 2.5.0
+ rc2_omacdone@Base 2.5.0
+ rc2_cmacinit@Base 2.5.0
+ rc2_cmacsetkey@Base 2.5.0
+ rc2_cmachash@Base 2.5.0
+ rc2_cmacdone@Base 2.5.0
+ rc2_cmac@Base 2.5.0
+ rc2_pmac1init@Base 2.5.0
+ rc2_pmac1setkey@Base 2.5.0
+ rc2_pmac1hash@Base 2.5.0
+ rc2_pmac1done@Base 2.5.0
+ rc2_pmac1@Base 2.5.0
## rc4
rc4_init@Base 2.0.0
rc5_counterbdry@Base 2.0.0
rc5_counter@Base 2.0.0
rc5_counterrand@Base 2.0.0
+ rc5_ccminit@Base 2.5.0
+ rc5_ccmreinit@Base 2.5.0
+ rc5_ccmnoncesz@Base 2.5.0
+ rc5_ccmtagsz@Base 2.5.0
+ rc5_ccmaadhash@Base 2.5.0
+ rc5_ccmencrypt@Base 2.5.0
+ rc5_ccmdecrypt@Base 2.5.0
+ rc5_ccmencryptdone@Base 2.5.0
+ rc5_ccmdecryptdone@Base 2.5.0
+ rc5_ccm@Base 2.5.0
+ rc5_eaxinit@Base 2.5.0
+ rc5_eaxreinit@Base 2.5.0
+ rc5_eaxsetkey@Base 2.5.0
+ rc5_eaxnoncesz@Base 2.5.0
+ rc5_eaxtagsz@Base 2.5.0
+ rc5_eaxaadinit@Base 2.5.0
+ rc5_eaxaadhash@Base 2.5.0
+ rc5_eaxencrypt@Base 2.5.0
+ rc5_eaxdecrypt@Base 2.5.0
+ rc5_eaxencryptdone@Base 2.5.0
+ rc5_eaxdecryptdone@Base 2.5.0
+ rc5_eax@Base 2.5.0
+ rc5_gcminit@Base 2.5.0
+ rc5_gcmreinit@Base 2.5.0
+ rc5_gcmsetkey@Base 2.5.0
+ rc5_gcmnoncesz@Base 2.5.0
+ rc5_gcmtagsz@Base 2.5.0
+ rc5_gcmaadinit@Base 2.5.0
+ rc5_gcmaadhash@Base 2.5.0
+ rc5_gcmencrypt@Base 2.5.0
+ rc5_gcmdecrypt@Base 2.5.0
+ rc5_gcmencryptdone@Base 2.5.0
+ rc5_gcmdecryptdone@Base 2.5.0
+ rc5_gcm@Base 2.5.0
+ rc5_ocb1init@Base 2.5.0
+ rc5_ocb1reinit@Base 2.5.0
+ rc5_ocb1setkey@Base 2.5.0
+ rc5_ocb1policy@Base 2.5.0
+ rc5_ocb1noncesz@Base 2.5.0
+ rc5_ocb1tagsz@Base 2.5.0
+ rc5_ocb1aadinit@Base 2.5.0
+ rc5_ocb1aadhash@Base 2.5.0
+ rc5_ocb1aadtag@Base 2.5.0
+ rc5_ocb1encrypt@Base 2.5.0
+ rc5_ocb1decrypt@Base 2.5.0
+ rc5_ocb1encryptdone@Base 2.5.0
+ rc5_ocb1decryptdone@Base 2.5.0
+ rc5_ocb1@Base 2.5.0
+ rc5_ocb3init@Base 2.5.0
+ rc5_ocb3step@Base 2.5.0
+ rc5_ocb3reinit@Base 2.5.0
+ rc5_ocb3setkey@Base 2.5.0
+ rc5_ocb3noncesz@Base 2.5.0
+ rc5_ocb3aadinit@Base 2.5.0
+ rc5_ocb3aadhash@Base 2.5.0
+ rc5_ocb3encrypt@Base 2.5.0
+ rc5_ocb3decrypt@Base 2.5.0
+ rc5_ocb3encryptdone@Base 2.5.0
+ rc5_ocb3decryptdone@Base 2.5.0
+ rc5_ocb3tagsz@Base 2.5.0
+ rc5_ocb3@Base 2.5.0
+ rc5_omacmasks@Base 2.5.0
+ rc5_omacpolicy@Base 2.5.0
+ rc5_omacdone@Base 2.5.0
+ rc5_cmacinit@Base 2.5.0
+ rc5_cmacsetkey@Base 2.5.0
+ rc5_cmachash@Base 2.5.0
+ rc5_cmacdone@Base 2.5.0
+ rc5_cmac@Base 2.5.0
+ rc5_pmac1init@Base 2.5.0
+ rc5_pmac1setkey@Base 2.5.0
+ rc5_pmac1hash@Base 2.5.0
+ rc5_pmac1done@Base 2.5.0
+ rc5_pmac1@Base 2.5.0
## rijndael
rijndael_init@Base 2.0.0
(optional)rijndael_ti@Base 2.1.5
(optional)rijndael_u@Base 2.1.5
(optional|arch=i386 amd64)rijndael_setup_x86ish_aesni@Base 2.3.0
+ (optional|arch=i386 amd64)rijndael_setup_x86ish_aesni_avx@Base 2.3.0
(optional|arch=armel armhf)rijndael_setup_arm_crypto@Base 2.2.5
(optional|arch=arm64)rijndael_setup_arm64_crypto@Base 2.4.3
(optional|arch=i386 amd64)rijndael_eblk_x86ish_aesni@Base 2.3.0
+ (optional|arch=i386 amd64)rijndael_eblk_x86ish_aesni_avx@Base 2.3.0
(optional|arch=armel armhf)rijndael_eblk_arm_crypto@Base 2.2.5
(optional|arch=arm64)rijndael_eblk_arm64_crypto@Base 2.4.3
(optional|arch=i386 amd64)rijndael_dblk_x86ish_aesni@Base 2.3.0
+ (optional|arch=i386 amd64)rijndael_dblk_x86ish_aesni_avx@Base 2.3.0
(optional|arch=armel armhf)rijndael_dblk_arm_crypto@Base 2.2.5
(optional|arch=arm64)rijndael_dblk_arm64_crypto@Base 2.4.3
rijndael_ecbinit@Base 2.1.1
rijndael_counterbdry@Base 2.0.0
rijndael_counter@Base 2.0.0
rijndael_counterrand@Base 2.0.0
+ rijndael_ccminit@Base 2.5.0
+ rijndael_ccmreinit@Base 2.5.0
+ rijndael_ccmnoncesz@Base 2.5.0
+ rijndael_ccmtagsz@Base 2.5.0
+ rijndael_ccmaadhash@Base 2.5.0
+ rijndael_ccmencrypt@Base 2.5.0
+ rijndael_ccmdecrypt@Base 2.5.0
+ rijndael_ccmencryptdone@Base 2.5.0
+ rijndael_ccmdecryptdone@Base 2.5.0
+ rijndael_ccm@Base 2.5.0
+ rijndael_eaxinit@Base 2.5.0
+ rijndael_eaxreinit@Base 2.5.0
+ rijndael_eaxsetkey@Base 2.5.0
+ rijndael_eaxnoncesz@Base 2.5.0
+ rijndael_eaxtagsz@Base 2.5.0
+ rijndael_eaxaadinit@Base 2.5.0
+ rijndael_eaxaadhash@Base 2.5.0
+ rijndael_eaxencrypt@Base 2.5.0
+ rijndael_eaxdecrypt@Base 2.5.0
+ rijndael_eaxencryptdone@Base 2.5.0
+ rijndael_eaxdecryptdone@Base 2.5.0
+ rijndael_eax@Base 2.5.0
+ rijndael_gcminit@Base 2.5.0
+ rijndael_gcmreinit@Base 2.5.0
+ rijndael_gcmsetkey@Base 2.5.0
+ rijndael_gcmnoncesz@Base 2.5.0
+ rijndael_gcmtagsz@Base 2.5.0
+ rijndael_gcmaadinit@Base 2.5.0
+ rijndael_gcmaadhash@Base 2.5.0
+ rijndael_gcmencrypt@Base 2.5.0
+ rijndael_gcmdecrypt@Base 2.5.0
+ rijndael_gcmencryptdone@Base 2.5.0
+ rijndael_gcmdecryptdone@Base 2.5.0
+ rijndael_gcm@Base 2.5.0
+ rijndael_ocb1init@Base 2.5.0
+ rijndael_ocb1reinit@Base 2.5.0
+ rijndael_ocb1setkey@Base 2.5.0
+ rijndael_ocb1policy@Base 2.5.0
+ rijndael_ocb1noncesz@Base 2.5.0
+ rijndael_ocb1tagsz@Base 2.5.0
+ rijndael_ocb1aadinit@Base 2.5.0
+ rijndael_ocb1aadhash@Base 2.5.0
+ rijndael_ocb1aadtag@Base 2.5.0
+ rijndael_ocb1encrypt@Base 2.5.0
+ rijndael_ocb1decrypt@Base 2.5.0
+ rijndael_ocb1encryptdone@Base 2.5.0
+ rijndael_ocb1decryptdone@Base 2.5.0
+ rijndael_ocb1@Base 2.5.0
+ rijndael_ocb3init@Base 2.5.0
+ rijndael_ocb3step@Base 2.5.0
+ rijndael_ocb3reinit@Base 2.5.0
+ rijndael_ocb3setkey@Base 2.5.0
+ rijndael_ocb3noncesz@Base 2.5.0
+ rijndael_ocb3aadinit@Base 2.5.0
+ rijndael_ocb3aadhash@Base 2.5.0
+ rijndael_ocb3encrypt@Base 2.5.0
+ rijndael_ocb3decrypt@Base 2.5.0
+ rijndael_ocb3encryptdone@Base 2.5.0
+ rijndael_ocb3decryptdone@Base 2.5.0
+ rijndael_ocb3tagsz@Base 2.5.0
+ rijndael_ocb3@Base 2.5.0
+ rijndael_omacmasks@Base 2.5.0
+ rijndael_omacpolicy@Base 2.5.0
+ rijndael_omacdone@Base 2.5.0
+ rijndael_cmacinit@Base 2.5.0
+ rijndael_cmacsetkey@Base 2.5.0
+ rijndael_cmachash@Base 2.5.0
+ rijndael_cmacdone@Base 2.5.0
+ rijndael_cmac@Base 2.5.0
+ rijndael_pmac1init@Base 2.5.0
+ rijndael_pmac1setkey@Base 2.5.0
+ rijndael_pmac1hash@Base 2.5.0
+ rijndael_pmac1done@Base 2.5.0
+ rijndael_pmac1@Base 2.5.0
## rijndael192
rijndael192_init@Base 2.0.0
rijndael192_counterbdry@Base 2.0.0
rijndael192_counter@Base 2.0.0
rijndael192_counterrand@Base 2.0.0
+ rijndael192_ccminit@Base 2.5.0
+ rijndael192_ccmreinit@Base 2.5.0
+ rijndael192_ccmnoncesz@Base 2.5.0
+ rijndael192_ccmtagsz@Base 2.5.0
+ rijndael192_ccmaadhash@Base 2.5.0
+ rijndael192_ccmencrypt@Base 2.5.0
+ rijndael192_ccmdecrypt@Base 2.5.0
+ rijndael192_ccmencryptdone@Base 2.5.0
+ rijndael192_ccmdecryptdone@Base 2.5.0
+ rijndael192_ccm@Base 2.5.0
+ rijndael192_eaxinit@Base 2.5.0
+ rijndael192_eaxreinit@Base 2.5.0
+ rijndael192_eaxsetkey@Base 2.5.0
+ rijndael192_eaxnoncesz@Base 2.5.0
+ rijndael192_eaxtagsz@Base 2.5.0
+ rijndael192_eaxaadinit@Base 2.5.0
+ rijndael192_eaxaadhash@Base 2.5.0
+ rijndael192_eaxencrypt@Base 2.5.0
+ rijndael192_eaxdecrypt@Base 2.5.0
+ rijndael192_eaxencryptdone@Base 2.5.0
+ rijndael192_eaxdecryptdone@Base 2.5.0
+ rijndael192_eax@Base 2.5.0
+ rijndael192_gcminit@Base 2.5.0
+ rijndael192_gcmreinit@Base 2.5.0
+ rijndael192_gcmsetkey@Base 2.5.0
+ rijndael192_gcmnoncesz@Base 2.5.0
+ rijndael192_gcmtagsz@Base 2.5.0
+ rijndael192_gcmaadinit@Base 2.5.0
+ rijndael192_gcmaadhash@Base 2.5.0
+ rijndael192_gcmencrypt@Base 2.5.0
+ rijndael192_gcmdecrypt@Base 2.5.0
+ rijndael192_gcmencryptdone@Base 2.5.0
+ rijndael192_gcmdecryptdone@Base 2.5.0
+ rijndael192_gcm@Base 2.5.0
+ rijndael192_ocb1init@Base 2.5.0
+ rijndael192_ocb1reinit@Base 2.5.0
+ rijndael192_ocb1setkey@Base 2.5.0
+ rijndael192_ocb1policy@Base 2.5.0
+ rijndael192_ocb1noncesz@Base 2.5.0
+ rijndael192_ocb1tagsz@Base 2.5.0
+ rijndael192_ocb1aadinit@Base 2.5.0
+ rijndael192_ocb1aadhash@Base 2.5.0
+ rijndael192_ocb1aadtag@Base 2.5.0
+ rijndael192_ocb1encrypt@Base 2.5.0
+ rijndael192_ocb1decrypt@Base 2.5.0
+ rijndael192_ocb1encryptdone@Base 2.5.0
+ rijndael192_ocb1decryptdone@Base 2.5.0
+ rijndael192_ocb1@Base 2.5.0
+ rijndael192_ocb3init@Base 2.5.0
+ rijndael192_ocb3step@Base 2.5.0
+ rijndael192_ocb3reinit@Base 2.5.0
+ rijndael192_ocb3setkey@Base 2.5.0
+ rijndael192_ocb3noncesz@Base 2.5.0
+ rijndael192_ocb3aadinit@Base 2.5.0
+ rijndael192_ocb3aadhash@Base 2.5.0
+ rijndael192_ocb3encrypt@Base 2.5.0
+ rijndael192_ocb3decrypt@Base 2.5.0
+ rijndael192_ocb3encryptdone@Base 2.5.0
+ rijndael192_ocb3decryptdone@Base 2.5.0
+ rijndael192_ocb3tagsz@Base 2.5.0
+ rijndael192_ocb3@Base 2.5.0
+ rijndael192_omacmasks@Base 2.5.0
+ rijndael192_omacpolicy@Base 2.5.0
+ rijndael192_omacdone@Base 2.5.0
+ rijndael192_cmacinit@Base 2.5.0
+ rijndael192_cmacsetkey@Base 2.5.0
+ rijndael192_cmachash@Base 2.5.0
+ rijndael192_cmacdone@Base 2.5.0
+ rijndael192_cmac@Base 2.5.0
+ rijndael192_pmac1init@Base 2.5.0
+ rijndael192_pmac1setkey@Base 2.5.0
+ rijndael192_pmac1hash@Base 2.5.0
+ rijndael192_pmac1done@Base 2.5.0
+ rijndael192_pmac1@Base 2.5.0
## rijndael256
rijndael256_init@Base 2.0.0
rijndael256_counterbdry@Base 2.0.0
rijndael256_counter@Base 2.0.0
rijndael256_counterrand@Base 2.0.0
+ rijndael256_ccminit@Base 2.5.0
+ rijndael256_ccmreinit@Base 2.5.0
+ rijndael256_ccmnoncesz@Base 2.5.0
+ rijndael256_ccmtagsz@Base 2.5.0
+ rijndael256_ccmaadhash@Base 2.5.0
+ rijndael256_ccmencrypt@Base 2.5.0
+ rijndael256_ccmdecrypt@Base 2.5.0
+ rijndael256_ccmencryptdone@Base 2.5.0
+ rijndael256_ccmdecryptdone@Base 2.5.0
+ rijndael256_ccm@Base 2.5.0
+ rijndael256_eaxinit@Base 2.5.0
+ rijndael256_eaxreinit@Base 2.5.0
+ rijndael256_eaxsetkey@Base 2.5.0
+ rijndael256_eaxnoncesz@Base 2.5.0
+ rijndael256_eaxtagsz@Base 2.5.0
+ rijndael256_eaxaadinit@Base 2.5.0
+ rijndael256_eaxaadhash@Base 2.5.0
+ rijndael256_eaxencrypt@Base 2.5.0
+ rijndael256_eaxdecrypt@Base 2.5.0
+ rijndael256_eaxencryptdone@Base 2.5.0
+ rijndael256_eaxdecryptdone@Base 2.5.0
+ rijndael256_eax@Base 2.5.0
+ rijndael256_gcminit@Base 2.5.0
+ rijndael256_gcmreinit@Base 2.5.0
+ rijndael256_gcmsetkey@Base 2.5.0
+ rijndael256_gcmnoncesz@Base 2.5.0
+ rijndael256_gcmtagsz@Base 2.5.0
+ rijndael256_gcmaadinit@Base 2.5.0
+ rijndael256_gcmaadhash@Base 2.5.0
+ rijndael256_gcmencrypt@Base 2.5.0
+ rijndael256_gcmdecrypt@Base 2.5.0
+ rijndael256_gcmencryptdone@Base 2.5.0
+ rijndael256_gcmdecryptdone@Base 2.5.0
+ rijndael256_gcm@Base 2.5.0
+ rijndael256_ocb1init@Base 2.5.0
+ rijndael256_ocb1reinit@Base 2.5.0
+ rijndael256_ocb1setkey@Base 2.5.0
+ rijndael256_ocb1policy@Base 2.5.0
+ rijndael256_ocb1noncesz@Base 2.5.0
+ rijndael256_ocb1tagsz@Base 2.5.0
+ rijndael256_ocb1aadinit@Base 2.5.0
+ rijndael256_ocb1aadhash@Base 2.5.0
+ rijndael256_ocb1aadtag@Base 2.5.0
+ rijndael256_ocb1encrypt@Base 2.5.0
+ rijndael256_ocb1decrypt@Base 2.5.0
+ rijndael256_ocb1encryptdone@Base 2.5.0
+ rijndael256_ocb1decryptdone@Base 2.5.0
+ rijndael256_ocb1@Base 2.5.0
+ rijndael256_ocb3init@Base 2.5.0
+ rijndael256_ocb3step@Base 2.5.0
+ rijndael256_ocb3reinit@Base 2.5.0
+ rijndael256_ocb3setkey@Base 2.5.0
+ rijndael256_ocb3noncesz@Base 2.5.0
+ rijndael256_ocb3aadinit@Base 2.5.0
+ rijndael256_ocb3aadhash@Base 2.5.0
+ rijndael256_ocb3encrypt@Base 2.5.0
+ rijndael256_ocb3decrypt@Base 2.5.0
+ rijndael256_ocb3encryptdone@Base 2.5.0
+ rijndael256_ocb3decryptdone@Base 2.5.0
+ rijndael256_ocb3tagsz@Base 2.5.0
+ rijndael256_ocb3@Base 2.5.0
+ rijndael256_omacmasks@Base 2.5.0
+ rijndael256_omacpolicy@Base 2.5.0
+ rijndael256_omacdone@Base 2.5.0
+ rijndael256_cmacinit@Base 2.5.0
+ rijndael256_cmacsetkey@Base 2.5.0
+ rijndael256_cmachash@Base 2.5.0
+ rijndael256_cmacdone@Base 2.5.0
+ rijndael256_cmac@Base 2.5.0
+ rijndael256_pmac1init@Base 2.5.0
+ rijndael256_pmac1setkey@Base 2.5.0
+ rijndael256_pmac1hash@Base 2.5.0
+ rijndael256_pmac1done@Base 2.5.0
+ rijndael256_pmac1@Base 2.5.0
## safer
safer_init@Base 2.0.0
safer_counterbdry@Base 2.0.0
safer_counter@Base 2.0.0
safer_counterrand@Base 2.0.0
+ safer_ccminit@Base 2.5.0
+ safer_ccmreinit@Base 2.5.0
+ safer_ccmnoncesz@Base 2.5.0
+ safer_ccmtagsz@Base 2.5.0
+ safer_ccmaadhash@Base 2.5.0
+ safer_ccmencrypt@Base 2.5.0
+ safer_ccmdecrypt@Base 2.5.0
+ safer_ccmencryptdone@Base 2.5.0
+ safer_ccmdecryptdone@Base 2.5.0
+ safer_ccm@Base 2.5.0
+ safer_eaxinit@Base 2.5.0
+ safer_eaxreinit@Base 2.5.0
+ safer_eaxsetkey@Base 2.5.0
+ safer_eaxnoncesz@Base 2.5.0
+ safer_eaxtagsz@Base 2.5.0
+ safer_eaxaadinit@Base 2.5.0
+ safer_eaxaadhash@Base 2.5.0
+ safer_eaxencrypt@Base 2.5.0
+ safer_eaxdecrypt@Base 2.5.0
+ safer_eaxencryptdone@Base 2.5.0
+ safer_eaxdecryptdone@Base 2.5.0
+ safer_eax@Base 2.5.0
+ safer_gcminit@Base 2.5.0
+ safer_gcmreinit@Base 2.5.0
+ safer_gcmsetkey@Base 2.5.0
+ safer_gcmnoncesz@Base 2.5.0
+ safer_gcmtagsz@Base 2.5.0
+ safer_gcmaadinit@Base 2.5.0
+ safer_gcmaadhash@Base 2.5.0
+ safer_gcmencrypt@Base 2.5.0
+ safer_gcmdecrypt@Base 2.5.0
+ safer_gcmencryptdone@Base 2.5.0
+ safer_gcmdecryptdone@Base 2.5.0
+ safer_gcm@Base 2.5.0
+ safer_ocb1init@Base 2.5.0
+ safer_ocb1reinit@Base 2.5.0
+ safer_ocb1setkey@Base 2.5.0
+ safer_ocb1policy@Base 2.5.0
+ safer_ocb1noncesz@Base 2.5.0
+ safer_ocb1tagsz@Base 2.5.0
+ safer_ocb1aadinit@Base 2.5.0
+ safer_ocb1aadhash@Base 2.5.0
+ safer_ocb1aadtag@Base 2.5.0
+ safer_ocb1encrypt@Base 2.5.0
+ safer_ocb1decrypt@Base 2.5.0
+ safer_ocb1encryptdone@Base 2.5.0
+ safer_ocb1decryptdone@Base 2.5.0
+ safer_ocb1@Base 2.5.0
+ safer_ocb3init@Base 2.5.0
+ safer_ocb3step@Base 2.5.0
+ safer_ocb3reinit@Base 2.5.0
+ safer_ocb3setkey@Base 2.5.0
+ safer_ocb3noncesz@Base 2.5.0
+ safer_ocb3aadinit@Base 2.5.0
+ safer_ocb3aadhash@Base 2.5.0
+ safer_ocb3encrypt@Base 2.5.0
+ safer_ocb3decrypt@Base 2.5.0
+ safer_ocb3encryptdone@Base 2.5.0
+ safer_ocb3decryptdone@Base 2.5.0
+ safer_ocb3tagsz@Base 2.5.0
+ safer_ocb3@Base 2.5.0
+ safer_omacmasks@Base 2.5.0
+ safer_omacpolicy@Base 2.5.0
+ safer_omacdone@Base 2.5.0
+ safer_cmacinit@Base 2.5.0
+ safer_cmacsetkey@Base 2.5.0
+ safer_cmachash@Base 2.5.0
+ safer_cmacdone@Base 2.5.0
+ safer_cmac@Base 2.5.0
+ safer_pmac1init@Base 2.5.0
+ safer_pmac1setkey@Base 2.5.0
+ safer_pmac1hash@Base 2.5.0
+ safer_pmac1done@Base 2.5.0
+ safer_pmac1@Base 2.5.0
## safersk
safersk_init@Base 2.0.0
safersk_counterbdry@Base 2.0.0
safersk_counter@Base 2.0.0
safersk_counterrand@Base 2.0.0
+ safersk_ccminit@Base 2.5.0
+ safersk_ccmreinit@Base 2.5.0
+ safersk_ccmnoncesz@Base 2.5.0
+ safersk_ccmtagsz@Base 2.5.0
+ safersk_ccmaadhash@Base 2.5.0
+ safersk_ccmencrypt@Base 2.5.0
+ safersk_ccmdecrypt@Base 2.5.0
+ safersk_ccmencryptdone@Base 2.5.0
+ safersk_ccmdecryptdone@Base 2.5.0
+ safersk_ccm@Base 2.5.0
+ safersk_eaxinit@Base 2.5.0
+ safersk_eaxreinit@Base 2.5.0
+ safersk_eaxsetkey@Base 2.5.0
+ safersk_eaxnoncesz@Base 2.5.0
+ safersk_eaxtagsz@Base 2.5.0
+ safersk_eaxaadinit@Base 2.5.0
+ safersk_eaxaadhash@Base 2.5.0
+ safersk_eaxencrypt@Base 2.5.0
+ safersk_eaxdecrypt@Base 2.5.0
+ safersk_eaxencryptdone@Base 2.5.0
+ safersk_eaxdecryptdone@Base 2.5.0
+ safersk_eax@Base 2.5.0
+ safersk_gcminit@Base 2.5.0
+ safersk_gcmreinit@Base 2.5.0
+ safersk_gcmsetkey@Base 2.5.0
+ safersk_gcmnoncesz@Base 2.5.0
+ safersk_gcmtagsz@Base 2.5.0
+ safersk_gcmaadinit@Base 2.5.0
+ safersk_gcmaadhash@Base 2.5.0
+ safersk_gcmencrypt@Base 2.5.0
+ safersk_gcmdecrypt@Base 2.5.0
+ safersk_gcmencryptdone@Base 2.5.0
+ safersk_gcmdecryptdone@Base 2.5.0
+ safersk_gcm@Base 2.5.0
+ safersk_ocb1init@Base 2.5.0
+ safersk_ocb1reinit@Base 2.5.0
+ safersk_ocb1setkey@Base 2.5.0
+ safersk_ocb1policy@Base 2.5.0
+ safersk_ocb1noncesz@Base 2.5.0
+ safersk_ocb1tagsz@Base 2.5.0
+ safersk_ocb1aadinit@Base 2.5.0
+ safersk_ocb1aadhash@Base 2.5.0
+ safersk_ocb1aadtag@Base 2.5.0
+ safersk_ocb1encrypt@Base 2.5.0
+ safersk_ocb1decrypt@Base 2.5.0
+ safersk_ocb1encryptdone@Base 2.5.0
+ safersk_ocb1decryptdone@Base 2.5.0
+ safersk_ocb1@Base 2.5.0
+ safersk_ocb3init@Base 2.5.0
+ safersk_ocb3step@Base 2.5.0
+ safersk_ocb3reinit@Base 2.5.0
+ safersk_ocb3setkey@Base 2.5.0
+ safersk_ocb3noncesz@Base 2.5.0
+ safersk_ocb3aadinit@Base 2.5.0
+ safersk_ocb3aadhash@Base 2.5.0
+ safersk_ocb3encrypt@Base 2.5.0
+ safersk_ocb3decrypt@Base 2.5.0
+ safersk_ocb3encryptdone@Base 2.5.0
+ safersk_ocb3decryptdone@Base 2.5.0
+ safersk_ocb3tagsz@Base 2.5.0
+ safersk_ocb3@Base 2.5.0
+ safersk_omacmasks@Base 2.5.0
+ safersk_omacpolicy@Base 2.5.0
+ safersk_omacdone@Base 2.5.0
+ safersk_cmacinit@Base 2.5.0
+ safersk_cmacsetkey@Base 2.5.0
+ safersk_cmachash@Base 2.5.0
+ safersk_cmacdone@Base 2.5.0
+ safersk_cmac@Base 2.5.0
+ safersk_pmac1init@Base 2.5.0
+ safersk_pmac1setkey@Base 2.5.0
+ safersk_pmac1hash@Base 2.5.0
+ safersk_pmac1done@Base 2.5.0
+ safersk_pmac1@Base 2.5.0
## salsa20
salsa20_init@Base 2.2.0
salsa2012_encrypt@Base 2.2.0
salsa20_encrypt@Base 2.2.0
(optional|arch=i386 amd64)salsa20_core_x86ish_sse2@Base 2.2.3
+ (optional|arch=i386 amd64)salsa20_core_x86ish_avx@Base 2.2.3
(optional|arch=armel armhf)salsa20_core_arm_neon@Base 2.2.3
(optional|arch=arm64)salsa20_core_arm64@Base 2.4.3
salsa208@Base 2.2.0
salsa208_ietf_rand@Base 2.4.2
salsa2012_ietf_rand@Base 2.4.2
salsa20_ietf_rand@Base 2.4.2
+ salsa208_naclbox@Base 2.5.0
+ salsa2012_naclbox@Base 2.5.0
+ salsa20_naclbox@Base 2.5.0
+ salsa208_poly1305@Base 2.5.0
+ salsa2012_poly1305@Base 2.5.0
+ salsa20_poly1305@Base 2.5.0
hsalsa208_prf@Base 2.2.0
hsalsa2012_prf@Base 2.2.0
hsalsa20_prf@Base 2.2.0
serpent_counterbdry@Base 2.0.0
serpent_counter@Base 2.0.0
serpent_counterrand@Base 2.0.0
+ serpent_ccminit@Base 2.5.0
+ serpent_ccmreinit@Base 2.5.0
+ serpent_ccmnoncesz@Base 2.5.0
+ serpent_ccmtagsz@Base 2.5.0
+ serpent_ccmaadhash@Base 2.5.0
+ serpent_ccmencrypt@Base 2.5.0
+ serpent_ccmdecrypt@Base 2.5.0
+ serpent_ccmencryptdone@Base 2.5.0
+ serpent_ccmdecryptdone@Base 2.5.0
+ serpent_ccm@Base 2.5.0
+ serpent_eaxinit@Base 2.5.0
+ serpent_eaxreinit@Base 2.5.0
+ serpent_eaxsetkey@Base 2.5.0
+ serpent_eaxnoncesz@Base 2.5.0
+ serpent_eaxtagsz@Base 2.5.0
+ serpent_eaxaadinit@Base 2.5.0
+ serpent_eaxaadhash@Base 2.5.0
+ serpent_eaxencrypt@Base 2.5.0
+ serpent_eaxdecrypt@Base 2.5.0
+ serpent_eaxencryptdone@Base 2.5.0
+ serpent_eaxdecryptdone@Base 2.5.0
+ serpent_eax@Base 2.5.0
+ serpent_gcminit@Base 2.5.0
+ serpent_gcmreinit@Base 2.5.0
+ serpent_gcmsetkey@Base 2.5.0
+ serpent_gcmnoncesz@Base 2.5.0
+ serpent_gcmtagsz@Base 2.5.0
+ serpent_gcmaadinit@Base 2.5.0
+ serpent_gcmaadhash@Base 2.5.0
+ serpent_gcmencrypt@Base 2.5.0
+ serpent_gcmdecrypt@Base 2.5.0
+ serpent_gcmencryptdone@Base 2.5.0
+ serpent_gcmdecryptdone@Base 2.5.0
+ serpent_gcm@Base 2.5.0
+ serpent_ocb1init@Base 2.5.0
+ serpent_ocb1reinit@Base 2.5.0
+ serpent_ocb1setkey@Base 2.5.0
+ serpent_ocb1policy@Base 2.5.0
+ serpent_ocb1noncesz@Base 2.5.0
+ serpent_ocb1tagsz@Base 2.5.0
+ serpent_ocb1aadinit@Base 2.5.0
+ serpent_ocb1aadhash@Base 2.5.0
+ serpent_ocb1aadtag@Base 2.5.0
+ serpent_ocb1encrypt@Base 2.5.0
+ serpent_ocb1decrypt@Base 2.5.0
+ serpent_ocb1encryptdone@Base 2.5.0
+ serpent_ocb1decryptdone@Base 2.5.0
+ serpent_ocb1@Base 2.5.0
+ serpent_ocb3init@Base 2.5.0
+ serpent_ocb3step@Base 2.5.0
+ serpent_ocb3reinit@Base 2.5.0
+ serpent_ocb3setkey@Base 2.5.0
+ serpent_ocb3noncesz@Base 2.5.0
+ serpent_ocb3aadinit@Base 2.5.0
+ serpent_ocb3aadhash@Base 2.5.0
+ serpent_ocb3encrypt@Base 2.5.0
+ serpent_ocb3decrypt@Base 2.5.0
+ serpent_ocb3encryptdone@Base 2.5.0
+ serpent_ocb3decryptdone@Base 2.5.0
+ serpent_ocb3tagsz@Base 2.5.0
+ serpent_ocb3@Base 2.5.0
+ serpent_omacmasks@Base 2.5.0
+ serpent_omacpolicy@Base 2.5.0
+ serpent_omacdone@Base 2.5.0
+ serpent_cmacinit@Base 2.5.0
+ serpent_cmacsetkey@Base 2.5.0
+ serpent_cmachash@Base 2.5.0
+ serpent_cmacdone@Base 2.5.0
+ serpent_cmac@Base 2.5.0
+ serpent_pmac1init@Base 2.5.0
+ serpent_pmac1setkey@Base 2.5.0
+ serpent_pmac1hash@Base 2.5.0
+ serpent_pmac1done@Base 2.5.0
+ serpent_pmac1@Base 2.5.0
## skipjack
skipjack_init@Base 2.0.0
skipjack_counterbdry@Base 2.0.0
skipjack_counter@Base 2.0.0
skipjack_counterrand@Base 2.0.0
+ skipjack_ccminit@Base 2.5.0
+ skipjack_ccmreinit@Base 2.5.0
+ skipjack_ccmnoncesz@Base 2.5.0
+ skipjack_ccmtagsz@Base 2.5.0
+ skipjack_ccmaadhash@Base 2.5.0
+ skipjack_ccmencrypt@Base 2.5.0
+ skipjack_ccmdecrypt@Base 2.5.0
+ skipjack_ccmencryptdone@Base 2.5.0
+ skipjack_ccmdecryptdone@Base 2.5.0
+ skipjack_ccm@Base 2.5.0
+ skipjack_eaxinit@Base 2.5.0
+ skipjack_eaxreinit@Base 2.5.0
+ skipjack_eaxsetkey@Base 2.5.0
+ skipjack_eaxnoncesz@Base 2.5.0
+ skipjack_eaxtagsz@Base 2.5.0
+ skipjack_eaxaadinit@Base 2.5.0
+ skipjack_eaxaadhash@Base 2.5.0
+ skipjack_eaxencrypt@Base 2.5.0
+ skipjack_eaxdecrypt@Base 2.5.0
+ skipjack_eaxencryptdone@Base 2.5.0
+ skipjack_eaxdecryptdone@Base 2.5.0
+ skipjack_eax@Base 2.5.0
+ skipjack_gcminit@Base 2.5.0
+ skipjack_gcmreinit@Base 2.5.0
+ skipjack_gcmsetkey@Base 2.5.0
+ skipjack_gcmnoncesz@Base 2.5.0
+ skipjack_gcmtagsz@Base 2.5.0
+ skipjack_gcmaadinit@Base 2.5.0
+ skipjack_gcmaadhash@Base 2.5.0
+ skipjack_gcmencrypt@Base 2.5.0
+ skipjack_gcmdecrypt@Base 2.5.0
+ skipjack_gcmencryptdone@Base 2.5.0
+ skipjack_gcmdecryptdone@Base 2.5.0
+ skipjack_gcm@Base 2.5.0
+ skipjack_ocb1init@Base 2.5.0
+ skipjack_ocb1reinit@Base 2.5.0
+ skipjack_ocb1setkey@Base 2.5.0
+ skipjack_ocb1policy@Base 2.5.0
+ skipjack_ocb1noncesz@Base 2.5.0
+ skipjack_ocb1tagsz@Base 2.5.0
+ skipjack_ocb1aadinit@Base 2.5.0
+ skipjack_ocb1aadhash@Base 2.5.0
+ skipjack_ocb1aadtag@Base 2.5.0
+ skipjack_ocb1encrypt@Base 2.5.0
+ skipjack_ocb1decrypt@Base 2.5.0
+ skipjack_ocb1encryptdone@Base 2.5.0
+ skipjack_ocb1decryptdone@Base 2.5.0
+ skipjack_ocb1@Base 2.5.0
+ skipjack_ocb3init@Base 2.5.0
+ skipjack_ocb3step@Base 2.5.0
+ skipjack_ocb3reinit@Base 2.5.0
+ skipjack_ocb3setkey@Base 2.5.0
+ skipjack_ocb3noncesz@Base 2.5.0
+ skipjack_ocb3aadinit@Base 2.5.0
+ skipjack_ocb3aadhash@Base 2.5.0
+ skipjack_ocb3encrypt@Base 2.5.0
+ skipjack_ocb3decrypt@Base 2.5.0
+ skipjack_ocb3encryptdone@Base 2.5.0
+ skipjack_ocb3decryptdone@Base 2.5.0
+ skipjack_ocb3tagsz@Base 2.5.0
+ skipjack_ocb3@Base 2.5.0
+ skipjack_omacmasks@Base 2.5.0
+ skipjack_omacpolicy@Base 2.5.0
+ skipjack_omacdone@Base 2.5.0
+ skipjack_cmacinit@Base 2.5.0
+ skipjack_cmacsetkey@Base 2.5.0
+ skipjack_cmachash@Base 2.5.0
+ skipjack_cmacdone@Base 2.5.0
+ skipjack_cmac@Base 2.5.0
+ skipjack_pmac1init@Base 2.5.0
+ skipjack_pmac1setkey@Base 2.5.0
+ skipjack_pmac1hash@Base 2.5.0
+ skipjack_pmac1done@Base 2.5.0
+ skipjack_pmac1@Base 2.5.0
## square
square_init@Base 2.0.0
square_counterbdry@Base 2.0.0
square_counter@Base 2.0.0
square_counterrand@Base 2.0.0
+ square_ccminit@Base 2.5.0
+ square_ccmreinit@Base 2.5.0
+ square_ccmnoncesz@Base 2.5.0
+ square_ccmtagsz@Base 2.5.0
+ square_ccmaadhash@Base 2.5.0
+ square_ccmencrypt@Base 2.5.0
+ square_ccmdecrypt@Base 2.5.0
+ square_ccmencryptdone@Base 2.5.0
+ square_ccmdecryptdone@Base 2.5.0
+ square_ccm@Base 2.5.0
+ square_eaxinit@Base 2.5.0
+ square_eaxreinit@Base 2.5.0
+ square_eaxsetkey@Base 2.5.0
+ square_eaxnoncesz@Base 2.5.0
+ square_eaxtagsz@Base 2.5.0
+ square_eaxaadinit@Base 2.5.0
+ square_eaxaadhash@Base 2.5.0
+ square_eaxencrypt@Base 2.5.0
+ square_eaxdecrypt@Base 2.5.0
+ square_eaxencryptdone@Base 2.5.0
+ square_eaxdecryptdone@Base 2.5.0
+ square_eax@Base 2.5.0
+ square_gcminit@Base 2.5.0
+ square_gcmreinit@Base 2.5.0
+ square_gcmsetkey@Base 2.5.0
+ square_gcmnoncesz@Base 2.5.0
+ square_gcmtagsz@Base 2.5.0
+ square_gcmaadinit@Base 2.5.0
+ square_gcmaadhash@Base 2.5.0
+ square_gcmencrypt@Base 2.5.0
+ square_gcmdecrypt@Base 2.5.0
+ square_gcmencryptdone@Base 2.5.0
+ square_gcmdecryptdone@Base 2.5.0
+ square_gcm@Base 2.5.0
+ square_ocb1init@Base 2.5.0
+ square_ocb1reinit@Base 2.5.0
+ square_ocb1setkey@Base 2.5.0
+ square_ocb1policy@Base 2.5.0
+ square_ocb1noncesz@Base 2.5.0
+ square_ocb1tagsz@Base 2.5.0
+ square_ocb1aadinit@Base 2.5.0
+ square_ocb1aadhash@Base 2.5.0
+ square_ocb1aadtag@Base 2.5.0
+ square_ocb1encrypt@Base 2.5.0
+ square_ocb1decrypt@Base 2.5.0
+ square_ocb1encryptdone@Base 2.5.0
+ square_ocb1decryptdone@Base 2.5.0
+ square_ocb1@Base 2.5.0
+ square_ocb3init@Base 2.5.0
+ square_ocb3step@Base 2.5.0
+ square_ocb3reinit@Base 2.5.0
+ square_ocb3setkey@Base 2.5.0
+ square_ocb3noncesz@Base 2.5.0
+ square_ocb3aadinit@Base 2.5.0
+ square_ocb3aadhash@Base 2.5.0
+ square_ocb3encrypt@Base 2.5.0
+ square_ocb3decrypt@Base 2.5.0
+ square_ocb3encryptdone@Base 2.5.0
+ square_ocb3decryptdone@Base 2.5.0
+ square_ocb3tagsz@Base 2.5.0
+ square_ocb3@Base 2.5.0
+ square_omacmasks@Base 2.5.0
+ square_omacpolicy@Base 2.5.0
+ square_omacdone@Base 2.5.0
+ square_cmacinit@Base 2.5.0
+ square_cmacsetkey@Base 2.5.0
+ square_cmachash@Base 2.5.0
+ square_cmacdone@Base 2.5.0
+ square_cmac@Base 2.5.0
+ square_pmac1init@Base 2.5.0
+ square_pmac1setkey@Base 2.5.0
+ square_pmac1hash@Base 2.5.0
+ square_pmac1done@Base 2.5.0
+ square_pmac1@Base 2.5.0
## tea
tea_init@Base 2.0.0
tea_counterbdry@Base 2.0.0
tea_counter@Base 2.0.0
tea_counterrand@Base 2.0.0
+ tea_ccminit@Base 2.5.0
+ tea_ccmreinit@Base 2.5.0
+ tea_ccmnoncesz@Base 2.5.0
+ tea_ccmtagsz@Base 2.5.0
+ tea_ccmaadhash@Base 2.5.0
+ tea_ccmencrypt@Base 2.5.0
+ tea_ccmdecrypt@Base 2.5.0
+ tea_ccmencryptdone@Base 2.5.0
+ tea_ccmdecryptdone@Base 2.5.0
+ tea_ccm@Base 2.5.0
+ tea_eaxinit@Base 2.5.0
+ tea_eaxreinit@Base 2.5.0
+ tea_eaxsetkey@Base 2.5.0
+ tea_eaxnoncesz@Base 2.5.0
+ tea_eaxtagsz@Base 2.5.0
+ tea_eaxaadinit@Base 2.5.0
+ tea_eaxaadhash@Base 2.5.0
+ tea_eaxencrypt@Base 2.5.0
+ tea_eaxdecrypt@Base 2.5.0
+ tea_eaxencryptdone@Base 2.5.0
+ tea_eaxdecryptdone@Base 2.5.0
+ tea_eax@Base 2.5.0
+ tea_gcminit@Base 2.5.0
+ tea_gcmreinit@Base 2.5.0
+ tea_gcmsetkey@Base 2.5.0
+ tea_gcmnoncesz@Base 2.5.0
+ tea_gcmtagsz@Base 2.5.0
+ tea_gcmaadinit@Base 2.5.0
+ tea_gcmaadhash@Base 2.5.0
+ tea_gcmencrypt@Base 2.5.0
+ tea_gcmdecrypt@Base 2.5.0
+ tea_gcmencryptdone@Base 2.5.0
+ tea_gcmdecryptdone@Base 2.5.0
+ tea_gcm@Base 2.5.0
+ tea_ocb1init@Base 2.5.0
+ tea_ocb1reinit@Base 2.5.0
+ tea_ocb1setkey@Base 2.5.0
+ tea_ocb1policy@Base 2.5.0
+ tea_ocb1noncesz@Base 2.5.0
+ tea_ocb1tagsz@Base 2.5.0
+ tea_ocb1aadinit@Base 2.5.0
+ tea_ocb1aadhash@Base 2.5.0
+ tea_ocb1aadtag@Base 2.5.0
+ tea_ocb1encrypt@Base 2.5.0
+ tea_ocb1decrypt@Base 2.5.0
+ tea_ocb1encryptdone@Base 2.5.0
+ tea_ocb1decryptdone@Base 2.5.0
+ tea_ocb1@Base 2.5.0
+ tea_ocb3init@Base 2.5.0
+ tea_ocb3step@Base 2.5.0
+ tea_ocb3reinit@Base 2.5.0
+ tea_ocb3setkey@Base 2.5.0
+ tea_ocb3noncesz@Base 2.5.0
+ tea_ocb3aadinit@Base 2.5.0
+ tea_ocb3aadhash@Base 2.5.0
+ tea_ocb3encrypt@Base 2.5.0
+ tea_ocb3decrypt@Base 2.5.0
+ tea_ocb3encryptdone@Base 2.5.0
+ tea_ocb3decryptdone@Base 2.5.0
+ tea_ocb3tagsz@Base 2.5.0
+ tea_ocb3@Base 2.5.0
+ tea_omacmasks@Base 2.5.0
+ tea_omacpolicy@Base 2.5.0
+ tea_omacdone@Base 2.5.0
+ tea_cmacinit@Base 2.5.0
+ tea_cmacsetkey@Base 2.5.0
+ tea_cmachash@Base 2.5.0
+ tea_cmacdone@Base 2.5.0
+ tea_cmac@Base 2.5.0
+ tea_pmac1init@Base 2.5.0
+ tea_pmac1setkey@Base 2.5.0
+ tea_pmac1hash@Base 2.5.0
+ tea_pmac1done@Base 2.5.0
+ tea_pmac1@Base 2.5.0
## twofish
twofish_fkinit@Base 2.0.0
twofish_counterbdry@Base 2.0.0
twofish_counter@Base 2.0.0
twofish_counterrand@Base 2.0.0
+ twofish_ccminit@Base 2.5.0
+ twofish_ccmreinit@Base 2.5.0
+ twofish_ccmnoncesz@Base 2.5.0
+ twofish_ccmtagsz@Base 2.5.0
+ twofish_ccmaadhash@Base 2.5.0
+ twofish_ccmencrypt@Base 2.5.0
+ twofish_ccmdecrypt@Base 2.5.0
+ twofish_ccmencryptdone@Base 2.5.0
+ twofish_ccmdecryptdone@Base 2.5.0
+ twofish_ccm@Base 2.5.0
+ twofish_eaxinit@Base 2.5.0
+ twofish_eaxreinit@Base 2.5.0
+ twofish_eaxsetkey@Base 2.5.0
+ twofish_eaxnoncesz@Base 2.5.0
+ twofish_eaxtagsz@Base 2.5.0
+ twofish_eaxaadinit@Base 2.5.0
+ twofish_eaxaadhash@Base 2.5.0
+ twofish_eaxencrypt@Base 2.5.0
+ twofish_eaxdecrypt@Base 2.5.0
+ twofish_eaxencryptdone@Base 2.5.0
+ twofish_eaxdecryptdone@Base 2.5.0
+ twofish_eax@Base 2.5.0
+ twofish_gcminit@Base 2.5.0
+ twofish_gcmreinit@Base 2.5.0
+ twofish_gcmsetkey@Base 2.5.0
+ twofish_gcmnoncesz@Base 2.5.0
+ twofish_gcmtagsz@Base 2.5.0
+ twofish_gcmaadinit@Base 2.5.0
+ twofish_gcmaadhash@Base 2.5.0
+ twofish_gcmencrypt@Base 2.5.0
+ twofish_gcmdecrypt@Base 2.5.0
+ twofish_gcmencryptdone@Base 2.5.0
+ twofish_gcmdecryptdone@Base 2.5.0
+ twofish_gcm@Base 2.5.0
+ twofish_ocb1init@Base 2.5.0
+ twofish_ocb1reinit@Base 2.5.0
+ twofish_ocb1setkey@Base 2.5.0
+ twofish_ocb1policy@Base 2.5.0
+ twofish_ocb1noncesz@Base 2.5.0
+ twofish_ocb1tagsz@Base 2.5.0
+ twofish_ocb1aadinit@Base 2.5.0
+ twofish_ocb1aadhash@Base 2.5.0
+ twofish_ocb1aadtag@Base 2.5.0
+ twofish_ocb1encrypt@Base 2.5.0
+ twofish_ocb1decrypt@Base 2.5.0
+ twofish_ocb1encryptdone@Base 2.5.0
+ twofish_ocb1decryptdone@Base 2.5.0
+ twofish_ocb1@Base 2.5.0
+ twofish_ocb3init@Base 2.5.0
+ twofish_ocb3step@Base 2.5.0
+ twofish_ocb3reinit@Base 2.5.0
+ twofish_ocb3setkey@Base 2.5.0
+ twofish_ocb3noncesz@Base 2.5.0
+ twofish_ocb3aadinit@Base 2.5.0
+ twofish_ocb3aadhash@Base 2.5.0
+ twofish_ocb3encrypt@Base 2.5.0
+ twofish_ocb3decrypt@Base 2.5.0
+ twofish_ocb3encryptdone@Base 2.5.0
+ twofish_ocb3decryptdone@Base 2.5.0
+ twofish_ocb3tagsz@Base 2.5.0
+ twofish_ocb3@Base 2.5.0
+ twofish_omacmasks@Base 2.5.0
+ twofish_omacpolicy@Base 2.5.0
+ twofish_omacdone@Base 2.5.0
+ twofish_cmacinit@Base 2.5.0
+ twofish_cmacsetkey@Base 2.5.0
+ twofish_cmachash@Base 2.5.0
+ twofish_cmacdone@Base 2.5.0
+ twofish_cmac@Base 2.5.0
+ twofish_pmac1init@Base 2.5.0
+ twofish_pmac1setkey@Base 2.5.0
+ twofish_pmac1hash@Base 2.5.0
+ twofish_pmac1done@Base 2.5.0
+ twofish_pmac1@Base 2.5.0
## xtea
xtea_init@Base 2.0.0
xtea_counterbdry@Base 2.0.0
xtea_counter@Base 2.0.0
xtea_counterrand@Base 2.0.0
+ xtea_ccminit@Base 2.5.0
+ xtea_ccmreinit@Base 2.5.0
+ xtea_ccmnoncesz@Base 2.5.0
+ xtea_ccmtagsz@Base 2.5.0
+ xtea_ccmaadhash@Base 2.5.0
+ xtea_ccmencrypt@Base 2.5.0
+ xtea_ccmdecrypt@Base 2.5.0
+ xtea_ccmencryptdone@Base 2.5.0
+ xtea_ccmdecryptdone@Base 2.5.0
+ xtea_ccm@Base 2.5.0
+ xtea_eaxinit@Base 2.5.0
+ xtea_eaxreinit@Base 2.5.0
+ xtea_eaxsetkey@Base 2.5.0
+ xtea_eaxnoncesz@Base 2.5.0
+ xtea_eaxtagsz@Base 2.5.0
+ xtea_eaxaadinit@Base 2.5.0
+ xtea_eaxaadhash@Base 2.5.0
+ xtea_eaxencrypt@Base 2.5.0
+ xtea_eaxdecrypt@Base 2.5.0
+ xtea_eaxencryptdone@Base 2.5.0
+ xtea_eaxdecryptdone@Base 2.5.0
+ xtea_eax@Base 2.5.0
+ xtea_gcminit@Base 2.5.0
+ xtea_gcmreinit@Base 2.5.0
+ xtea_gcmsetkey@Base 2.5.0
+ xtea_gcmnoncesz@Base 2.5.0
+ xtea_gcmtagsz@Base 2.5.0
+ xtea_gcmaadinit@Base 2.5.0
+ xtea_gcmaadhash@Base 2.5.0
+ xtea_gcmencrypt@Base 2.5.0
+ xtea_gcmdecrypt@Base 2.5.0
+ xtea_gcmencryptdone@Base 2.5.0
+ xtea_gcmdecryptdone@Base 2.5.0
+ xtea_gcm@Base 2.5.0
+ xtea_ocb1init@Base 2.5.0
+ xtea_ocb1reinit@Base 2.5.0
+ xtea_ocb1setkey@Base 2.5.0
+ xtea_ocb1policy@Base 2.5.0
+ xtea_ocb1noncesz@Base 2.5.0
+ xtea_ocb1tagsz@Base 2.5.0
+ xtea_ocb1aadinit@Base 2.5.0
+ xtea_ocb1aadhash@Base 2.5.0
+ xtea_ocb1aadtag@Base 2.5.0
+ xtea_ocb1encrypt@Base 2.5.0
+ xtea_ocb1decrypt@Base 2.5.0
+ xtea_ocb1encryptdone@Base 2.5.0
+ xtea_ocb1decryptdone@Base 2.5.0
+ xtea_ocb1@Base 2.5.0
+ xtea_ocb3init@Base 2.5.0
+ xtea_ocb3step@Base 2.5.0
+ xtea_ocb3reinit@Base 2.5.0
+ xtea_ocb3setkey@Base 2.5.0
+ xtea_ocb3noncesz@Base 2.5.0
+ xtea_ocb3aadinit@Base 2.5.0
+ xtea_ocb3aadhash@Base 2.5.0
+ xtea_ocb3encrypt@Base 2.5.0
+ xtea_ocb3decrypt@Base 2.5.0
+ xtea_ocb3encryptdone@Base 2.5.0
+ xtea_ocb3decryptdone@Base 2.5.0
+ xtea_ocb3tagsz@Base 2.5.0
+ xtea_ocb3@Base 2.5.0
+ xtea_omacmasks@Base 2.5.0
+ xtea_omacpolicy@Base 2.5.0
+ xtea_omacdone@Base 2.5.0
+ xtea_cmacinit@Base 2.5.0
+ xtea_cmacsetkey@Base 2.5.0
+ xtea_cmachash@Base 2.5.0
+ xtea_cmacdone@Base 2.5.0
+ xtea_cmac@Base 2.5.0
+ xtea_pmac1init@Base 2.5.0
+ xtea_pmac1setkey@Base 2.5.0
+ xtea_pmac1hash@Base 2.5.0
+ xtea_pmac1done@Base 2.5.0
+ xtea_pmac1@Base 2.5.0
## gcrc32
gcrc32@Base 2.1.0
## dh
dh_gen@Base 2.1.1
- dh_kcdsagen@Base 2.1.1
- dh_limlee@Base 2.2.4
+ dh_kcdsagen@Base 2.5.1+
+ dh_limlee@Base 2.5.1+
dh_checkparam@Base 2.1.1
dh_parse@Base 2.1.1
dhbin_parse@Base 2.1.1
key_structsteal@Base 2.1.1
key_mksubkeyiter@Base 2.1.1
key_nextsubkey@Base 2.1.1
- key_copydata@Base 2.1.2
+ key_copydata@Base 2.5.1+
key_incref@Base 2.1.1
- key_split@Base 2.1.1
+ key_split@Base 2.5.1+
key_drop@Base 2.1.1
key_destroy@Base 2.1.1
key_do@Base 2.1.1
## key-misc
key_byid@Base 2.1.1
- key_bytag@Base 2.1.1
+ key_bytag@Base 2.5.1+
key_bytype@Base 2.1.1
key_qtag@Base 2.1.1
key_expired@Base 2.1.1
+catacomb (2.5.1) experimental; urgency=medium
+
+ * Merge changes from 2.4.4.
+
+ -- Mark Wooding <mdw@distorted.org.uk> Sun, 29 Sep 2019 17:50:59 +0100
+
+catacomb (2.5.0) experimental; urgency=medium
+
+ * catacomb: MACs based on blockciphers: PMAC1 and CMAC (also known as
+ OMAC).
+ * catacomb: Authenticated Encryption with Additional Data (AEAD)
+ schemes. Some based on blockciphers: CCM, EAX, GCM (with CPU-specific
+ acceleration), OCB1 and OCB3 (OCB2 is broken). Also Salsa20 and
+ ChaCha20 with Poly1305: the RFC7539 scheme, and the NaCl `secret_box'
+ transform.
+ * catacomb: Implement Grantham's Frobenius test. Combine it with
+ Rabin--Miller, as Baillie--PSW, for testing given primes.
+ * catacomb-bin (catcrypt): Support AEAD schemes for bulk crypto.
+ * catacomb-bin (perftest): Options for batching; report cycle counts
+ where available.
+ * Many internal improvements: better documentation, debugging, testing,
+ etc.
+
+ -- Mark Wooding <mdw@distorted.org.uk> Sat, 21 Sep 2019 21:26:44 +0100
+
catacomb (2.4.5) experimental; urgency=medium
* catacomb: Fix memory leak in key-file error handling.
Section: libs
Priority: extra
Build-Depends: debhelper (>= 10), python, valgrind [!armel], pkg-config,
- mlib-dev (>= 2.2.2.1)
+ mlib-dev (>= 2.3.0)
Maintainer: Mark Wooding <mdw@distorted.org.uk>
Standards-Version: 3.1.1
pkginclude_HEADERS += pgen.h
libmath_la_SOURCES += pgen.c
libmath_la_SOURCES += pgen-gcd.c
+libmath_la_SOURCES += pgen-granfrob.c
libmath_la_SOURCES += pgen-simul.c
libmath_la_SOURCES += pgen-stdev.c
-TESTS += pgen.t$(EXEEXT)
+TESTS += pgen.t$(EXEEXT) pgen-granfrob.t$(EXEEXT)
EXTRA_DIST += t/pgen
## Finding primitive elements in finite fields.
#define M26 0x03ffffffu
#define M25 0x01ffffffu
-#define B26 0x04000000u
#define B25 0x02000000u
#define B24 0x01000000u
((i) == 5 || (i) == 10 || (i) == 15 || (i) == 20 || (i) == 25 ? 9 : 10)
#define NPIECE 26
-#define B10 0x0400
-#define B9 0x200
-#define B8 0x100
#define M10 0x3ff
#define M9 0x1ff
+#define B9 0x200
+#define B8 0x100
#endif
#define NPIECE 16
#define P p28
-#define B28 0x10000000u
#define B27 0x08000000u
#define M28 0x0fffffffu
-#define M27 0x07ffffffu
#define M32 0xffffffffu
#elif FGOLDI_IMPL == 12
#define NPIECE 40
#define P p12
-#define B12 0x1000u
#define B11 0x0800u
#define B10 0x0400u
#define M12 0xfffu
#define M11 0x7ffu
-#define M10 0x3ffu
#define M8 0xffu
#endif
/* --- Main approximation --- *
*
- * We use the Newton-Raphson recurrence relation
+ * The Newton--Raphson method finds approximate zeroes of a function by
+ * starting with a guess and repeatedly refining the guess by approximating
+ * the function near the guess by its tangent at the guess
+ * %$x$%-coordinate, using where the tangent cuts the %$x$%-axis as the new
+ * guess.
*
- * %$x_{i+1} = x_i - \frac{x_i^2 - a}{2 x_i}$%
+ * Given a function %$f(x)$% and a guess %$x_i$%, the tangent has the
+ * equation %$y = f(x_i) + f'(x_i) (x - x_i)$%, which is zero when
*
- * We inspect the term %$q = x^2 - a$% to see when to stop. Increasing
- * %$x$% is pointless when %$-q < 2 x + 1$%.
+ * %$\displaystyle x = x_i - \frac{f(x_i)}{f'(x_i)}
+ *
+ * We set %$f(x) = x^2 - a$%, so our recurrence will be
+ *
+ * %$\displaystyle x_{i+1} = x_i - \frac{x_i^2 - a}{2 x_i}$%
+ *
+ * It's possible to simplify this, but it's useful to see %$q = x_i^2 - a$%
+ * so that we know when to stop. We want the largest integer not larger
+ * than the true square root. If %$q > 0$% then %$x_i$% is definitely too
+ * large, and we should decrease it by at least one even if the adjustment
+ * term %$(x_i^2 - a)/2 x$% is less than one.
+ *
+ * Suppose, then, that %$q \le 0$%. Then %$(x_i + 1)^2 - a = {}$%
+ * $%x_i^2 + 2 x_i + 1 - a = q + 2 x_i + 1$%. Hence, if %$q \ge -2 x_i$%
+ * then %$x_i + 1$% is an overestimate and we should settle where we are.
+ * Otherwise, %$x_i + 1$% is an underestimate -- but, in this case the
+ * adjustment will always be at least one.
*/
for (;;) {
#if CPUFAM_X86
MAYBE_REDC4(x86_sse2)
+ MAYBE_REDC4(x86_avx)
#endif
#if CPUFAM_AMD64
MAYBE_REDC4(amd64_sse2)
+ MAYBE_REDC4(amd64_avx)
#endif
static redccore__functype *pick_redccore(void)
{
#if CPUFAM_X86
+ DISPATCH_PICK_COND(mpmont_reduce, maybe_redc4_x86_avx,
+ cpu_feature_p(CPUFEAT_X86_AVX));
DISPATCH_PICK_COND(mpmont_reduce, maybe_redc4_x86_sse2,
cpu_feature_p(CPUFEAT_X86_SSE2));
#endif
#if CPUFAM_AMD64
+ DISPATCH_PICK_COND(mpmont_reduce, maybe_redc4_amd64_avx,
+ cpu_feature_p(CPUFEAT_X86_AVX));
DISPATCH_PICK_COND(mpmont_reduce, maybe_redc4_amd64_sse2,
cpu_feature_p(CPUFEAT_X86_SSE2));
#endif
#if CPUFAM_X86
MAYBE_MUL4(x86_sse2)
+ MAYBE_MUL4(x86_avx)
#endif
#if CPUFAM_AMD64
MAYBE_MUL4(amd64_sse2)
+ MAYBE_MUL4(amd64_avx)
#endif
static mulcore__functype *pick_mulcore(void)
{
#if CPUFAM_X86
+ DISPATCH_PICK_COND(mpmont_mul, maybe_mul4_x86_avx,
+ cpu_feature_p(CPUFEAT_X86_AVX));
DISPATCH_PICK_COND(mpmont_mul, maybe_mul4_x86_sse2,
cpu_feature_p(CPUFEAT_X86_SSE2));
#endif
#if CPUFAM_AMD64
+ DISPATCH_PICK_COND(mpmont_mul, maybe_mul4_amd64_avx,
+ cpu_feature_p(CPUFEAT_X86_AVX));
DISPATCH_PICK_COND(mpmont_mul, maybe_mul4_amd64_sse2,
cpu_feature_p(CPUFEAT_X86_SSE2));
#endif
/// MA 02111-1307, USA.
///--------------------------------------------------------------------------
-/// External definitions.
+/// Preliminaries.
#include "config.h"
#include "asm-common.h"
-///--------------------------------------------------------------------------
-/// Prologue.
-
.arch pentium4
+
.text
///--------------------------------------------------------------------------
.macro mulcore r, i, slo, shi, d0, d1=nil, d2=nil, d3=nil
// Multiply R_I by the expanded operand SLO/SHI, and leave the pieces
// of the product in registers D0, D1, D2, D3.
- pshufd \d0, \r, SHUF(3, \i, 3, \i) // (r_i, ?, r_i, ?)
+ pshufd \d0, \r, SHUF(\i, 3, \i, 3) // (r_i, ?; r_i, ?)
.ifnes "\d1", "nil"
- movdqa \d1, \slo // (s'_0, s'_1, s''_0, s''_1)
+ movdqa \d1, \slo // (s'_0, s'_1; s''_0, s''_1)
.endif
.ifnes "\d3", "nil"
- movdqa \d3, \shi // (s'_2, s'_3, s''_2, s''_3)
+ movdqa \d3, \shi // (s'_2, s'_3; s''_2, s''_3)
.endif
.ifnes "\d1", "nil"
- psrldq \d1, 4 // (s'_1, s''_0, s''_1, 0)
+ psrldq \d1, 4 // (s'_1, s''_0; s''_1, 0)
.endif
.ifnes "\d2", "nil"
- movdqa \d2, \d0 // another copy of (r_i, ?, r_i, ?)
+ movdqa \d2, \d0 // another copy of (r_i, ?; r_i, ?)
.endif
.ifnes "\d3", "nil"
- psrldq \d3, 4 // (s'_3, s''_2, s''_3, 0)
+ psrldq \d3, 4 // (s'_3, s''_2; s''_3, 0)
.endif
.ifnes "\d1", "nil"
- pmuludq \d1, \d0 // (r_i s'_1, r_i s''_1)
+ pmuludq \d1, \d0 // (r_i s'_1; r_i s''_1)
.endif
.ifnes "\d3", "nil"
- pmuludq \d3, \d0 // (r_i s'_3, r_i s''_3)
+ pmuludq \d3, \d0 // (r_i s'_3; r_i s''_3)
.endif
.ifnes "\d2", "nil"
- pmuludq \d2, \shi // (r_i s'_2, r_i s''_2)
+ pmuludq \d2, \shi // (r_i s'_2; r_i s''_2)
.endif
- pmuludq \d0, \slo // (r_i s'_0, r_i s''_0)
+ pmuludq \d0, \slo // (r_i s'_0; r_i s''_0)
.endm
.macro accum c0, c1=nil, c2=nil, c3=nil
// lane 0 or 1 of D; the high two lanes of D are clobbered. On
// completion, XMM3 is clobbered. If CC is `nil', then the
// contribution which would have been added to it is left in C.
- pshufd xmm3, \c, SHUF(2, 3, 3, 3) // (?, ?, ?, t = c'' mod B)
- psrldq xmm3, 12 // (t, 0, 0, 0) = (t, 0)
- pslldq xmm3, 2 // (t b, 0)
- paddq \c, xmm3 // (c' + t b, c'')
+ pshufd xmm3, \c, SHUF(3, 3, 3, 2) // (?, ?; ?, t = c'' mod B)
+ psrldq xmm3, 12 // (t, 0; 0, 0) = (t; 0)
+ pslldq xmm3, 2 // (t b; 0)
+ paddq \c, xmm3 // (c' + t b; c'')
.ifeqs "\pos", "lo"
movdqa \d, \c
.else
// of the value represented in C are written at POS in D, and the
// remaining bits are left at the bottom of T.
movdqa \t, \c
- psllq \t, 16 // (?, c'' b)
- pslldq \c, 8 // (0, c')
- paddq \t, \c // (?, c' + c'' b)
- psrldq \t, 8 // c' + c'' b
+ psllq \t, 16 // (?; c'' b)
+ pslldq \c, 8 // (0; c')
+ paddq \t, \c // (?; c' + c'' b)
+ psrldq \t, 8 // (c' + c'' b; 0) = (c; 0)
.ifeqs "\pos", "lo"
movdqa \d, \t
.else
punpckldq \d, \t
.endif
- psrldq \t, 4 // floor((c' + c'' b)/B)
+ psrldq \t, 4 // (floor(c/B); 0)
.endm
.macro expand z, a, b, c=nil, d=nil
// On entry, A and C hold packed 128-bit values, and Z is zero. On
// exit, A:B and C:D together hold the same values in expanded
// form. If C is `nil', then only expand A to A:B.
- movdqa \b, \a // (a_0, a_1, a_2, a_3)
+ movdqa \b, \a // (a_0, a_1; a_2, a_3)
.ifnes "\c", "nil"
- movdqa \d, \c // (c_0, c_1, c_2, c_3)
+ movdqa \d, \c // (c_0, c_1; c_2, c_3)
.endif
- punpcklwd \a, \z // (a'_0, a''_0, a'_1, a''_1)
- punpckhwd \b, \z // (a'_2, a''_2, a'_3, a''_3)
+ punpcklwd \a, \z // (a'_0, a''_0; a'_1, a''_1)
+ punpckhwd \b, \z // (a'_2, a''_2; a'_3, a''_3)
.ifnes "\c", "nil"
- punpcklwd \c, \z // (c'_0, c''_0, c'_1, c''_1)
- punpckhwd \d, \z // (c'_2, c''_2, c'_3, c''_3)
+ punpcklwd \c, \z // (c'_0, c''_0; c'_1, c''_1)
+ punpckhwd \d, \z // (c'_2, c''_2; c'_3, c''_3)
.endif
- pshufd \a, \a, SHUF(3, 1, 2, 0) // (a'_0, a'_1, a''_0, a''_1)
- pshufd \b, \b, SHUF(3, 1, 2, 0) // (a'_2, a'_3, a''_2, a''_3)
+ pshufd \a, \a, SHUF(0, 2, 1, 3) // (a'_0, a'_1; a''_0, a''_1)
+ pshufd \b, \b, SHUF(0, 2, 1, 3) // (a'_2, a'_3; a''_2, a''_3)
.ifnes "\c", "nil"
- pshufd \c, \c, SHUF(3, 1, 2, 0) // (c'_0, c'_1, c''_0, c''_1)
- pshufd \d, \d, SHUF(3, 1, 2, 0) // (c'_2, c'_3, c''_2, c''_3)
+ pshufd \c, \c, SHUF(0, 2, 1, 3) // (c'_0, c'_1; c''_0, c''_1)
+ pshufd \d, \d, SHUF(0, 2, 1, 3) // (c'_2, c'_3; c''_2, c''_3)
.endif
.endm
// we can do that, we must gather them together.
movdqa \t, \c0
movdqa \u, \c1
- punpcklqdq \t, \c2 // (y'_0, y'_2)
- punpckhqdq \c0, \c2 // (y''_0, y''_2)
- punpcklqdq \u, \c3 // (y'_1, y'_3)
- punpckhqdq \c1, \c3 // (y''_1, y''_3)
+ punpcklqdq \t, \c2 // (y'_0; y'_2)
+ punpckhqdq \c0, \c2 // (y''_0; y''_2)
+ punpcklqdq \u, \c3 // (y'_1; y'_3)
+ punpckhqdq \c1, \c3 // (y''_1; y''_3)
// Now split the double-prime pieces. The high (up to) 48 bits will
// go up; the low 16 bits go down.
movdqa \c3, \c1
psllq \c2, 48
psllq \c3, 48
- psrlq \c0, 16 // high parts of (y''_0, y''_2)
- psrlq \c1, 16 // high parts of (y''_1, y''_3)
- psrlq \c2, 32 // low parts of (y''_0, y''_2)
- psrlq \c3, 32 // low parts of (y''_1, y''_3)
+ psrlq \c0, 16 // high parts of (y''_0; y''_2)
+ psrlq \c1, 16 // high parts of (y''_1; y''_3)
+ psrlq \c2, 32 // low parts of (y''_0; y''_2)
+ psrlq \c3, 32 // low parts of (y''_1; y''_3)
.ifnes "\hi", "nil"
movdqa \hi, \c1
.endif
- pslldq \c1, 8 // high part of (0, y''_1)
+ pslldq \c1, 8 // high part of (0; y''_1)
paddq \t, \c2 // propagate down
paddq \u, \c3
- paddq \t, \c1 // and up: (y_0, y_2)
- paddq \u, \c0 // (y_1, y_3)
+ paddq \t, \c1 // and up: (y_0; y_2)
+ paddq \u, \c0 // (y_1; y_3)
.ifnes "\hi", "nil"
- psrldq \hi, 8 // high part of (y''_3, 0)
+ psrldq \hi, 8 // high part of (y''_3; 0)
.endif
// Finally extract the answer. This complicated dance is better than
// storing to memory and loading, because the piecemeal stores
// inhibit store forwarding.
- movdqa \c3, \t // (y_0, y_1)
- movdqa \lo, \t // (y^*_0, ?, ?, ?)
- psrldq \t, 8 // (y_2, 0)
- psrlq \c3, 32 // (floor(y_0/B), ?)
- paddq \c3, \u // (y_1 + floor(y_0/B), ?)
- movdqa \c1, \c3 // (y^*_1, ?, ?, ?)
- psrldq \u, 8 // (y_3, 0)
- psrlq \c3, 32 // (floor((y_1 B + y_0)/B^2, ?)
- paddq \c3, \t // (y_2 + floor((y_1 B + y_0)/B^2, ?)
- punpckldq \lo, \c3 // (y^*_0, y^*_2, ?, ?)
- psrlq \c3, 32 // (floor((y_2 B^2 + y_1 B + y_0)/B^3, ?)
- paddq \c3, \u // (y_3 + floor((y_2 B^2 + y_1 B + y_0)/B^3, ?)
+ movdqa \c3, \t // (y_0; ?)
+ movdqa \lo, \t // (y^*_0, ?; ?, ?)
+ psrldq \t, 8 // (y_2; 0)
+ psrlq \c3, 32 // (floor(y_0/B); ?)
+ paddq \c3, \u // (y_1 + floor(y_0/B); ?)
+ movdqa \c1, \c3 // (y^*_1, ?; ?, ?)
+ psrldq \u, 8 // (y_3; 0)
+ psrlq \c3, 32 // (floor((y_1 B + y_0)/B^2; ?)
+ paddq \c3, \t // (y_2 + floor((y_1 B + y_0)/B^2; ?)
+ punpckldq \lo, \c3 // (y^*_0, y^*_2; ?, ?)
+ psrlq \c3, 32 // (floor((y_2 B^2 + y_1 B + y_0)/B^3; ?)
+ paddq \c3, \u // (y_3 + floor((y_2 B^2 + y_1 B + y_0)/B^3; ?)
.ifnes "\hi", "nil"
movdqa \t, \c3
pxor \u, \u
.endif
- punpckldq \c1, \c3 // (y^*_1, y^*_3, ?, ?)
+ punpckldq \c1, \c3 // (y^*_1, y^*_3; ?, ?)
.ifnes "\hi", "nil"
psrlq \t, 32 // very high bits of y
paddq \hi, \t
// On exit, the carry registers, including XMM15, are updated to hold
// C + A; XMM0, XMM1, XMM2, and XMM3 are clobbered. The other
// registers are preserved.
- movd xmm0, [rdi + 0] // (a_0, 0)
- movd xmm1, [rdi + 4] // (a_1, 0)
- movd xmm2, [rdi + 8] // (a_2, 0)
- movd xmm15, [rdi + 12] // (a_3, 0)
- paddq xmm12, xmm0 // (c'_0 + a_0, c''_0)
- paddq xmm13, xmm1 // (c'_1 + a_1, c''_1)
- paddq xmm14, xmm2 // (c'_2 + a_2, c''_2 + a_3 b)
+ movd xmm0, [rdi + 0] // (a_0; 0)
+ movd xmm1, [rdi + 4] // (a_1; 0)
+ movd xmm2, [rdi + 8] // (a_2; 0)
+ movd xmm15, [rdi + 12] // (a_3; 0)
+ paddq xmm12, xmm0 // (c'_0 + a_0; c''_0)
+ paddq xmm13, xmm1 // (c'_1 + a_1; c''_1)
+ paddq xmm14, xmm2 // (c'_2 + a_2; c''_2 + a_3 b)
.endm
///--------------------------------------------------------------------------
mulcore xmm7, 1, xmm10, xmm11, xmm0, xmm1, xmm2
accum xmm4, xmm5, xmm6
- punpckldq xmm12, xmm15 // (w_0, 0, w_1, 0)
- punpckhdq xmm14, xmm15 // (w_2, 0, w_3, 0)
+ punpckldq xmm12, xmm15 // (w_0, 0; w_1, 0)
+ punpckhdq xmm14, xmm15 // (w_2, 0; w_3, 0)
mulcore xmm7, 2, xmm10, xmm11, xmm0, xmm1
accum xmm5, xmm6
mulcore xmm7, 3, xmm10, xmm11, xmm0
accum xmm6
- punpckldq xmm12, xmm2 // (w_0, 0, 0, 0)
- punpckldq xmm14, xmm2 // (w_2, 0, 0, 0)
- punpckhdq xmm13, xmm2 // (w_1, 0, 0, 0)
- punpckhdq xmm15, xmm2 // (w_3, 0, 0, 0)
+ punpckldq xmm12, xmm2 // (w_0, 0; 0, 0)
+ punpckldq xmm14, xmm2 // (w_2, 0; 0, 0)
+ punpckhdq xmm13, xmm2 // (w_1, 0; 0, 0)
+ punpckhdq xmm15, xmm2 // (w_3, 0; 0, 0)
// That's lots of pieces. Now we have to assemble the answer.
squash xmm3, xmm4, xmm5, xmm6, xmm0, xmm1, xmm10
mulcore xmm7, 1, xmm8, xmm9, xmm0, xmm1, xmm2
accum xmm4, xmm5, xmm6
- punpckldq xmm12, xmm15 // (w_0, 0, w_1, 0)
- punpckhdq xmm14, xmm15 // (w_2, 0, w_3, 0)
+ punpckldq xmm12, xmm15 // (w_0, 0; w_1, 0)
+ punpckhdq xmm14, xmm15 // (w_2, 0; w_3, 0)
mulcore xmm7, 2, xmm8, xmm9, xmm0, xmm1
accum xmm5, xmm6
mulcore xmm7, 3, xmm8, xmm9, xmm0
accum xmm6
- punpckldq xmm12, xmm2 // (w_0, 0, 0, 0)
- punpckldq xmm14, xmm2 // (w_2, 0, 0, 0)
- punpckhdq xmm13, xmm2 // (w_1, 0, 0, 0)
- punpckhdq xmm15, xmm2 // (w_3, 0, 0, 0)
+ punpckldq xmm12, xmm2 // (w_0, 0; 0, 0)
+ punpckldq xmm14, xmm2 // (w_2, 0; 0, 0)
+ punpckhdq xmm13, xmm2 // (w_1, 0; 0, 0)
+ punpckhdq xmm15, xmm2 // (w_3, 0; 0, 0)
// That's lots of pieces. Now we have to assemble the answer.
squash xmm3, xmm4, xmm5, xmm6, xmm0, xmm1, xmm10
///--------------------------------------------------------------------------
/// Bulk multipliers.
+FUNC(mpx_umul4_amd64_avx)
+ .arch .avx
+ vzeroupper
+ endprologue
+ .arch pentium4
+ENDFUNC
+
FUNC(mpx_umul4_amd64_sse2)
// void mpx_umul4_amd64_sse2(mpw *dv, const mpw *av, const mpw *avl,
// const mpw *bv, const mpw *bvl);
ENDFUNC
+FUNC(mpxmont_mul4_amd64_avx)
+ .arch .avx
+ vzeroupper
+ endprologue
+ .arch pentium4
+ENDFUNC
+
FUNC(mpxmont_mul4_amd64_sse2)
// void mpxmont_mul4_amd64_sse2(mpw *dv, const mpw *av, const mpw *bv,
// const mpw *nv, size_t n, const mpw *mi);
ENDFUNC
+FUNC(mpxmont_redc4_amd64_avx)
+ .arch .avx
+ vzeroupper
+ endprologue
+ .arch pentium4
+ENDFUNC
+
FUNC(mpxmont_redc4_amd64_sse2)
// void mpxmont_redc4_amd64_sse2(mpw *dv, mpw *dvl, const mpw *nv,
// size_t n, const mpw *mi);
.endm
.macro testldcarry
- movdqu xmm12, [rcx + 0] // (c'_0, c''_0)
- movdqu xmm13, [rcx + 16] // (c'_1, c''_1)
- movdqu xmm14, [rcx + 32] // (c'_2, c''_2)
+ movdqu xmm12, [rcx + 0] // (c'_0; c''_0)
+ movdqu xmm13, [rcx + 16] // (c'_1; c''_1)
+ movdqu xmm14, [rcx + 32] // (c'_2; c''_2)
.endm
.macro testtop u=nil
/// MA 02111-1307, USA.
///--------------------------------------------------------------------------
-/// External definitions.
+/// Preliminaries.
#include "config.h"
#include "asm-common.h"
-///--------------------------------------------------------------------------
-/// Prologue.
-
.arch pentium4
+
.text
///--------------------------------------------------------------------------
.macro mulcore r, s, d0, d1=nil, d2=nil, d3=nil
// Load a word r_i from R, multiply by the expanded operand [S], and
// leave the pieces of the product in registers D0, D1, D2, D3.
- movd \d0, \r // (r_i, 0, 0, 0)
+ movd \d0, \r // (r_i, 0; 0, 0)
.ifnes "\d1", "nil"
- movdqa \d1, [\s] // (s'_0, s'_1, s''_0, s''_1)
+ movdqa \d1, [\s] // (s'_0, s'_1; s''_0, s''_1)
.endif
.ifnes "\d3", "nil"
- movdqa \d3, [\s + 16] // (s'_2, s'_3, s''_2, s''_3)
+ movdqa \d3, [\s + 16] // (s'_2, s'_3; s''_2, s''_3)
.endif
- pshufd \d0, \d0, SHUF(3, 0, 3, 0) // (r_i, ?, r_i, ?)
+ pshufd \d0, \d0, SHUF(0, 3, 0, 3) // (r_i, ?; r_i, ?)
.ifnes "\d1", "nil"
- psrldq \d1, 4 // (s'_1, s''_0, s''_1, 0)
+ psrldq \d1, 4 // (s'_1, s''_0; s''_1, 0)
.endif
.ifnes "\d2", "nil"
.ifnes "\d3", "nil"
- movdqa \d2, \d3 // another copy of (s'_2, s'_3, ...)
+ movdqa \d2, \d3 // another copy of (s'_2, s'_3; ...)
.else
- movdqa \d2, \d0 // another copy of (r_i, ?, r_i, ?)
+ movdqa \d2, \d0 // another copy of (r_i, ?; r_i, ?)
.endif
.endif
.ifnes "\d3", "nil"
- psrldq \d3, 4 // (s'_3, s''_2, s''_3, 0)
+ psrldq \d3, 4 // (s'_3, s''_2; s''_3, 0)
.endif
.ifnes "\d1", "nil"
- pmuludq \d1, \d0 // (r_i s'_1, r_i s''_1)
+ pmuludq \d1, \d0 // (r_i s'_1; r_i s''_1)
.endif
.ifnes "\d3", "nil"
- pmuludq \d3, \d0 // (r_i s'_3, r_i s''_3)
+ pmuludq \d3, \d0 // (r_i s'_3; r_i s''_3)
.endif
.ifnes "\d2", "nil"
.ifnes "\d3", "nil"
- pmuludq \d2, \d0 // (r_i s'_2, r_i s''_2)
+ pmuludq \d2, \d0 // (r_i s'_2; r_i s''_2)
.else
pmuludq \d2, [\s + 16]
.endif
.endif
- pmuludq \d0, [\s] // (r_i s'_0, r_i s''_0)
+ pmuludq \d0, [\s] // (r_i s'_0; r_i s''_0)
.endm
.macro accum c0, c1=nil, c2=nil, c3=nil
// carry registers. On completion, XMM3 is clobbered. If CC is
// `nil', then the contribution which would have been added to it is
// left in C.
- pshufd xmm3, \c, SHUF(2, 3, 3, 3) // (?, ?, ?, t = c'' mod B)
- psrldq xmm3, 12 // (t, 0, 0, 0) = (t, 0)
- pslldq xmm3, 2 // (t b, 0)
- paddq \c, xmm3 // (c' + t b, c'')
+ pshufd xmm3, \c, SHUF(3, 3, 3, 2) // (?, ?; ?, t = c'' mod B)
+ psrldq xmm3, 12 // (t, 0; 0, 0) = (t, 0)
+ pslldq xmm3, 2 // (t b; 0)
+ paddq \c, xmm3 // (c' + t b; c'')
movd \d, \c
psrlq \c, 32 // floor(c/B)
.ifnes "\cc", "nil"
// of the value represented in C are written to D, and the remaining
// bits are left at the bottom of T.
movdqa \t, \c
- psllq \t, 16 // (?, c'' b)
- pslldq \c, 8 // (0, c')
- paddq \t, \c // (?, c' + c'' b)
- psrldq \t, 8 // c' + c'' b
+ psllq \t, 16 // (?; c'' b)
+ pslldq \c, 8 // (0; c')
+ paddq \t, \c // (?; c' + c'' b)
+ psrldq \t, 8 // (c' + c'' b; 0) = (c; 0)
movd \d, \t
- psrldq \t, 4 // floor((c' + c'' b)/B)
+ psrldq \t, 4 // (floor(c/B); 0)
.endm
.macro expand z, a, b, c=nil, d=nil
// On entry, A and C hold packed 128-bit values, and Z is zero. On
// exit, A:B and C:D together hold the same values in expanded
// form. If C is `nil', then only expand A to A:B.
- movdqa \b, \a // (a_0, a_1, a_2, a_3)
+ movdqa \b, \a // (a_0, a_1; a_2, a_3)
.ifnes "\c", "nil"
- movdqa \d, \c // (c_0, c_1, c_2, c_3)
+ movdqa \d, \c // (c_0, c_1; c_2, c_3)
.endif
- punpcklwd \a, \z // (a'_0, a''_0, a'_1, a''_1)
- punpckhwd \b, \z // (a'_2, a''_2, a'_3, a''_3)
+ punpcklwd \a, \z // (a'_0, a''_0; a'_1, a''_1)
+ punpckhwd \b, \z // (a'_2, a''_2; a'_3, a''_3)
.ifnes "\c", "nil"
- punpcklwd \c, \z // (c'_0, c''_0, c'_1, c''_1)
- punpckhwd \d, \z // (c'_2, c''_2, c'_3, c''_3)
+ punpcklwd \c, \z // (c'_0, c''_0; c'_1, c''_1)
+ punpckhwd \d, \z // (c'_2, c''_2; c'_3, c''_3)
.endif
- pshufd \a, \a, SHUF(3, 1, 2, 0) // (a'_0, a'_1, a''_0, a''_1)
- pshufd \b, \b, SHUF(3, 1, 2, 0) // (a'_2, a'_3, a''_2, a''_3)
+ pshufd \a, \a, SHUF(0, 2, 1, 3) // (a'_0, a'_1; a''_0, a''_1)
+ pshufd \b, \b, SHUF(0, 2, 1, 3) // (a'_2, a'_3; a''_2, a''_3)
.ifnes "\c", "nil"
- pshufd \c, \c, SHUF(3, 1, 2, 0) // (c'_0, c'_1, c''_0, c''_1)
- pshufd \d, \d, SHUF(3, 1, 2, 0) // (c'_2, c'_3, c''_2, c''_3)
+ pshufd \c, \c, SHUF(0, 2, 1, 3) // (c'_0, c'_1; c''_0, c''_1)
+ pshufd \d, \d, SHUF(0, 2, 1, 3) // (c'_2, c'_3; c''_2, c''_3)
.endif
.endm
// we can do that, we must gather them together.
movdqa \t, \c0
movdqa \u, \c1
- punpcklqdq \t, \c2 // (y'_0, y'_2)
- punpckhqdq \c0, \c2 // (y''_0, y''_2)
- punpcklqdq \u, \c3 // (y'_1, y'_3)
- punpckhqdq \c1, \c3 // (y''_1, y''_3)
+ punpcklqdq \t, \c2 // (y'_0; y'_2)
+ punpckhqdq \c0, \c2 // (y''_0; y''_2)
+ punpcklqdq \u, \c3 // (y'_1; y'_3)
+ punpckhqdq \c1, \c3 // (y''_1; y''_3)
// Now split the double-prime pieces. The high (up to) 48 bits will
// go up; the low 16 bits go down.
movdqa \c3, \c1
psllq \c2, 48
psllq \c3, 48
- psrlq \c0, 16 // high parts of (y''_0, y''_2)
- psrlq \c1, 16 // high parts of (y''_1, y''_3)
- psrlq \c2, 32 // low parts of (y''_0, y''_2)
- psrlq \c3, 32 // low parts of (y''_1, y''_3)
+ psrlq \c0, 16 // high parts of (y''_0; y''_2)
+ psrlq \c1, 16 // high parts of (y''_1; y''_3)
+ psrlq \c2, 32 // low parts of (y''_0; y''_2)
+ psrlq \c3, 32 // low parts of (y''_1; y''_3)
.ifnes "\hi", "nil"
movdqa \hi, \c1
.endif
- pslldq \c1, 8 // high part of (0, y''_1)
+ pslldq \c1, 8 // high part of (0; y''_1)
paddq \t, \c2 // propagate down
paddq \u, \c3
- paddq \t, \c1 // and up: (y_0, y_2)
- paddq \u, \c0 // (y_1, y_3)
+ paddq \t, \c1 // and up: (y_0; y_2)
+ paddq \u, \c0 // (y_1; y_3)
.ifnes "\hi", "nil"
- psrldq \hi, 8 // high part of (y''_3, 0)
+ psrldq \hi, 8 // high part of (y''_3; 0)
.endif
// Finally extract the answer. This complicated dance is better than
// storing to memory and loading, because the piecemeal stores
// inhibit store forwarding.
- movdqa \c3, \t // (y_0, y_1)
- movdqa \lo, \t // (y^*_0, ?, ?, ?)
- psrldq \t, 8 // (y_2, 0)
- psrlq \c3, 32 // (floor(y_0/B), ?)
- paddq \c3, \u // (y_1 + floor(y_0/B), ?)
- movdqa \c1, \c3 // (y^*_1, ?, ?, ?)
- psrldq \u, 8 // (y_3, 0)
- psrlq \c3, 32 // (floor((y_1 B + y_0)/B^2, ?)
- paddq \c3, \t // (y_2 + floor((y_1 B + y_0)/B^2, ?)
- punpckldq \lo, \c3 // (y^*_0, y^*_2, ?, ?)
- psrlq \c3, 32 // (floor((y_2 B^2 + y_1 B + y_0)/B^3, ?)
- paddq \c3, \u // (y_3 + floor((y_2 B^2 + y_1 B + y_0)/B^3, ?)
+ movdqa \c3, \t // (y_0; ?)
+ movdqa \lo, \t // (y^*_0, ?; ?, ?)
+ psrldq \t, 8 // (y_2; 0)
+ psrlq \c3, 32 // (floor(y_0/B); ?)
+ paddq \c3, \u // (y_1 + floor(y_0/B); ?)
+ movdqa \c1, \c3 // (y^*_1, ?; ?, ?)
+ psrldq \u, 8 // (y_3; 0)
+ psrlq \c3, 32 // (floor((y_1 B + y_0)/B^2; ?)
+ paddq \c3, \t // (y_2 + floor((y_1 B + y_0)/B^2; ?)
+ punpckldq \lo, \c3 // (y^*_0, y^*_2; ?, ?)
+ psrlq \c3, 32 // (floor((y_2 B^2 + y_1 B + y_0)/B^3; ?)
+ paddq \c3, \u // (y_3 + floor((y_2 B^2 + y_1 B + y_0)/B^3; ?)
.ifnes "\hi", "nil"
movdqa \t, \c3
pxor \u, \u
.endif
- punpckldq \c1, \c3 // (y^*_1, y^*_3, ?, ?)
+ punpckldq \c1, \c3 // (y^*_1, y^*_3; ?, ?)
.ifnes "\hi", "nil"
psrlq \t, 32 // very high bits of y
paddq \hi, \t
// On exit, the carry registers, including XMM7, are updated to hold
// C + A; XMM0, XMM1, XMM2, and XMM3 are clobbered. The other
// registers are preserved.
- movd xmm0, [edi + 0] // (a_0, 0)
- movd xmm1, [edi + 4] // (a_1, 0)
- movd xmm2, [edi + 8] // (a_2, 0)
- movd xmm7, [edi + 12] // (a_3, 0)
-
- paddq xmm4, xmm0 // (c'_0 + a_0, c''_0)
- paddq xmm5, xmm1 // (c'_1 + a_1, c''_1)
- paddq xmm6, xmm2 // (c'_2 + a_2, c''_2 + a_3 b)
+ movd xmm0, [edi + 0] // (a_0; 0)
+ movd xmm1, [edi + 4] // (a_1; 0)
+ movd xmm2, [edi + 8] // (a_2; 0)
+ movd xmm7, [edi + 12] // (a_3; 0)
+
+ paddq xmm4, xmm0 // (c'_0 + a_0; c''_0)
+ paddq xmm5, xmm1 // (c'_1 + a_1; c''_1)
+ paddq xmm6, xmm2 // (c'_2 + a_2; c''_2 + a_3 b)
.endm
///--------------------------------------------------------------------------
///--------------------------------------------------------------------------
/// Bulk multipliers.
+FUNC(mpx_umul4_x86_avx)
+ .arch .avx
+ vzeroupper
+ endprologue
+ // and drop through...
+ .arch pentium4
+ENDFUNC
+
FUNC(mpx_umul4_x86_sse2)
// void mpx_umul4_x86_sse2(mpw *dv, const mpw *av, const mpw *avl,
// const mpw *bv, const mpw *bvl);
pushreg ebx
pushreg esi
pushreg edi
- setfp ebp
+ setfp
and esp, ~15
sub esp, 32
endprologue
ENDFUNC
+FUNC(mpxmont_mul4_x86_avx)
+ .arch .avx
+ vzeroupper
+ endprologue
+ // and drop through...
+ .arch pentium4
+ENDFUNC
+
FUNC(mpxmont_mul4_x86_sse2)
// void mpxmont_mul4_x86_sse2(mpw *dv, const mpw *av, const mpw *bv,
// const mpw *nv, size_t n, const mpw *mi);
pushreg ebx
pushreg esi
pushreg edi
- setfp ebp
+ setfp
and esp, ~15
sub esp, 112
endprologue
ENDFUNC
+FUNC(mpxmont_redc4_x86_avx)
+ .arch .avx
+ vzeroupper
+ endprologue
+ // and drop through...
+ .arch pentium4
+ENDFUNC
+
FUNC(mpxmont_redc4_x86_sse2)
// void mpxmont_redc4_x86_sse2(mpw *dv, mpw *dvl, const mpw *nv,
// size_t n, const mpw *mi);
pushreg ebx
pushreg esi
pushreg edi
- setfp ebp
+ setfp
and esp, ~15
sub esp, 76
endprologue
pushreg ebx
pushreg esi
pushreg edi
- setfp ebp
+ setfp
and esp, ~15
sub esp, 3*32 + 4*4
endprologue
.macro testldcarry c
mov ecx, \c // -> c
- movdqu xmm4, [ecx + 0] // (c'_0, c''_0)
- movdqu xmm5, [ecx + 16] // (c'_1, c''_1)
- movdqu xmm6, [ecx + 32] // (c'_2, c''_2)
+ movdqu xmm4, [ecx + 0] // (c'_0; c''_0)
+ movdqu xmm5, [ecx + 16] // (c'_1; c''_1)
+ movdqu xmm6, [ecx + 32] // (c'_2; c''_2)
.endm
.macro testexpand v=nil, y=nil
#if CPUFAM_X86
MAYBE_UMUL4(x86_sse2)
+ MAYBE_UMUL4(x86_avx)
#endif
#if CPUFAM_AMD64
MAYBE_UMUL4(amd64_sse2)
+ MAYBE_UMUL4(amd64_avx)
#endif
static mpx_umul__functype *pick_umul(void)
{
#if CPUFAM_X86
+ DISPATCH_PICK_COND(mpx_umul, maybe_umul4_x86_avx,
+ cpu_feature_p(CPUFEAT_X86_AVX));
DISPATCH_PICK_COND(mpx_umul, maybe_umul4_x86_sse2,
cpu_feature_p(CPUFEAT_X86_SSE2));
#endif
#if CPUFAM_AMD64
+ DISPATCH_PICK_COND(mpx_umul, maybe_umul4_amd64_avx,
+ cpu_feature_p(CPUFEAT_X86_AVX));
DISPATCH_PICK_COND(mpx_umul, maybe_umul4_amd64_sse2,
cpu_feature_p(CPUFEAT_X86_SSE2));
#endif
--- /dev/null
+/* -*-c-*-
+ *
+ * Grantham's Frobenius primality test
+ *
+ * (c) 2018 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "mp.h"
+#include "mpmont.h"
+#include "mpscan.h"
+#include "pgen.h"
+
+#include "mptext.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+static int squarep(mp *n)
+{
+ mp *t = MP_NEW;
+ int rc;
+
+ if (MP_NEGP(n)) return (0);
+ t = mp_sqrt(t, n); t = mp_sqr(t, t);
+ rc = MP_EQ(t, n); mp_drop(t); return (rc);
+}
+
+/* --- @pgen_granfrob@ --- *
+ *
+ * Arguments: @mp *n@ = an integer to test
+ * @int a, b@ = coefficients; if @a@ is zero then choose
+ * automatically
+ *
+ * Returns: One of the @PGEN_...@ codes.
+ *
+ * Use: Performs a quadratic version of Grantham's Frobenius
+ * primality test, which is a simple extension of the standard
+ * Lucas test.
+ *
+ * If %$a^2 - 4 b$% is a perfect square then the test can't
+ * work; this function returns @PGEN_ABORT@ under these
+ * circumstances.
+ */
+
+int pgen_granfrob(mp *n, int a, int b)
+{
+ mp *v = MP_NEW, *w = MP_NEW, *aa = MP_NEW, *bb = MP_NEW, *bi = MP_NEW,
+ *k = MP_NEW, *x = MP_NEW, *y = MP_NEW, *z = MP_NEW, *t, *u;
+ mp ma; mpw wa;
+ mp mb; mpw wb;
+ mp md; mpw wd; int d;
+ mpmont mm;
+ mpscan msc;
+ int e, bit, rc;
+
+ /* Maybe this is a no-hoper. */
+ if (MP_NEGP(n)) return (PGEN_FAIL);
+ if (MP_EQ(n, MP_TWO)) return (PGEN_DONE);
+ if (!MP_ODDP(n)) return (PGEN_FAIL);
+
+ /* First, build the parameters as large integers. */
+ mp_build(&ma, &wa, &wa + 1); mp_build(&mb, &wb, &wb + 1);
+ mp_build(&md, &wd, &wd + 1);
+ mpmont_create(&mm, n);
+
+ /* Prepare the Lucas sequence parameters. Here, %$\Delta$% is the
+ * disciminant of the polynomial %$p(x) = x^2 - a x + b$%, i.e.,
+ * %$\Delta = a^2 - 4 b$%.
+ */
+ if (a) {
+ /* Explicit parameters. Just set them and check that they'll work. */
+
+ if (a >= 0) wa = a; else { wa = -a; ma.f |= MP_NEG; }
+ if (b >= 0) wb = b; else { wb = -b; mb.f |= MP_NEG; }
+ d = a*a - 4*b;
+ if (d >= 0) wd = d; else { wd = -d; md.f |= MP_NEG; }
+
+ /* Determine the quadratic character of %$\Delta$%. If %$(\Delta | n)$%
+ * is zero then we'll have a problem, but we'll catch that case with the
+ * GCD check below.
+ */
+ e = mp_jacobi(&md, n);
+
+ /* If %$\Delta$% is a perfect square then the test can't work. */
+ if (e == 1 && squarep(&md)) { rc = PGEN_ABORT; goto end; }
+ } else {
+ /* Determine parameters. Use Selfridge's `Method A': choose the first
+ * %$\Delta$% from the sequence %$5$%, %$-7$%, %%\dots%%, such that
+ * %$(\Delta | n) = -1$%.
+ */
+
+ wa = 1; wd = 5;
+ for (;;) {
+ e = mp_jacobi(&md, n); if (e != +1) break;
+ if (wd == 25 && squarep(n)) { rc = PGEN_FAIL; goto end; }
+ wd += 2; md.f ^= MP_NEG;
+ }
+ a = 1; d = wd;
+ if (md.f&MP_NEG) { wb = (wd + 1)/4; d = -d; }
+ else { wb = (wd - 1)/4; mb.f |= MP_NEG; }
+ b = (1 - d)/4;
+ }
+
+ /* The test won't work if %$\gcd(2 a b \Delta, n) \ne 1$%. */
+ x = mp_lsl(x, &ma, 1); x = mp_mul(x, x, &mb); x = mp_mul(x, x, &md);
+ mp_gcd(&y, 0, 0, x, n);
+ if (!MP_EQ(y, MP_ONE))
+ { rc = MP_EQ(y, n) ? PGEN_ABORT : PGEN_FAIL; goto end; }
+
+ /* Now we use binary a Lucas chain to evaluate %$V_{n-e}(a, b) \pmod{n}$%.
+ * Here,
+ *
+ * * %$U_{i+1}(a, b) = a U_i(a, b) - b U_{i-1}(a, b)$%, and
+ * * %$V_{i+1}(a, b) = a V_i(a, b) - b V_{i-1}(a, b)$%; with
+ * * %$U_0(a, b) = 0$%, $%U_1(a, b) = 1$%, %$V_0(a, b) = 2$%, and
+ * %$V_1(a, b) = a$%.
+ *
+ * To compute this, we use the handy identities
+ *
+ * %$V_{i+j}(a, b) = V_i(a, b) V_j(a, b) - b^i V_{j-i}(a, b)$%
+ *
+ * and
+ *
+ * %$U_i(a, b) = (2 V_{i+1}(a, b) - a V_i(a, b))/\Delta$%.
+ *
+ * Let %$k = n - e$%. Given %$V_i(a, b)$% and %$V_{i+1}(a, b)$%, we can
+ * determine either %$V_{2i}(a, b)$% and %$V_{2i+1}(a, b)$%, or
+ * %$V_{2i+1}(a, b)$% and %$V_{2i+2}(a, b)$%.
+ *
+ * To do this, suppose that %$n < 2^\ell$% and %$0 \le i \le \ell%; we'll
+ * start with %$i = 0$%. Divide %$n = n_i 2^{\ell-i} + n'_i$% with
+ * %$n'_i < 2^{\ell-i}$%. To do this, we maintain %$v_i = V_{n_i}(a, b)$%,
+ * %$w_i = V_{n_i+1}(a, b)$%, and %$b_i = b^{n_i}$%, all modulo %$n$%. If
+ * %$n'_i < 2^{\ell-i-1}$% then we have %$n'_{i+1} = n'_i$% and
+ * %$n_{i+i} = 2 n_i$%; otherwise %$n'_{i+1} = n'_i - 2^{\ell-i-1}$% and
+ * %$n_{i+i} = 2 n_i + 1$%.
+ */
+ k = mp_add(k, n, e > 0 ? MP_MONE : MP_ONE);
+ aa = mpmont_mul(&mm, aa, &ma, mm.r2);
+ bb = mpmont_mul(&mm, bb, &mb, mm.r2); bi = MP_COPY(mm.r);
+ v = mpmont_mul(&mm, v, MP_TWO, mm.r2); w = MP_COPY(aa);
+
+ for (mpscan_rinitx(&msc, k->v, k->vl); mpscan_rstep(&msc); ) {
+ bit = mpscan_rbit(&msc);
+
+ /* We will want %$x = V_{n_i+1}(a, b) = V_{n_i} V_{n_i+1} - a b^{n_i}$%,
+ * but we don't yet know whether this is %$v_{i+1}$% or %$w_{i+1}$%.
+ */
+ x = mpmont_mul(&mm, x, v, w);
+ if (a == 1) x = mp_sub(x, x, bi);
+ else { y = mpmont_mul(&mm, y, aa, bi); x = mp_sub(x, x, y); }
+ if (MP_NEGP(x)) x = mp_add(x, x, n);
+
+ if (!bit) {
+ /* We're in the former case: %$n_{i+i} = 2 n_i$%. So %$w_{i+1} = x$%,
+ * %$v_{i+1} = (v_i^2 - 2 b_i$%, and %$b_{i+1} = b_i^2$%.
+ */
+
+ y = mp_sqr(y, v); y = mpmont_reduce(&mm, y, y);
+ y = mp_sub(y, y, bi); if (MP_NEGP(y)) y = mp_add(y, y, n);
+ y = mp_sub(y, y, bi); if (MP_NEGP(y)) y = mp_add(y, y, n);
+ bi = mp_sqr(bi, bi); bi = mpmont_reduce(&mm, bi, bi);
+ t = v; u = w; v = y; w = x; x = t; y = u;
+ } else {
+ /* We're in the former case: %$n_{i+i} = 2 n_i + 1$%. So
+ * %$v_{i+1} = x$%, %$w_{i+1} = w_i^2 - 2 b b^i$%$%, and
+ * %$b_{i+1} = b b_i^2$%.
+ */
+
+ y = mp_sqr(y, w); y = mpmont_reduce(&mm, y, y);
+ z = mpmont_mul(&mm, z, bi, bb);
+ y = mp_sub(y, y, z); if (MP_NEGP(y)) y = mp_add(y, y, n);
+ y = mp_sub(y, y, z); if (MP_NEGP(y)) y = mp_add(y, y, n);
+ bi = mpmont_mul(&mm, bi, bi, z);
+ t = v; u = w; v = x; w = y; x = t; y = u;
+ }
+ }
+
+ /* The Lucas test is that %$U_k(a, b) \equiv 0 \pmod{n}$% if %$n$% is
+ * prime. I'm assured that
+ *
+ * %$U_k(a, b) = (2 V_{k+1}(a, b) - a V_k(a, b))/\Delta$%
+ *
+ * so this is just a matter of checking that %$2 w - a v \equiv 0$%.
+ */
+ x = mp_add(x, w, w); y = mp_sub(y, x, n);
+ if (!MP_NEGP(y)) { t = x; x = y; y = t; }
+ if (a == 1) x = mp_sub(x, x, v);
+ else { y = mpmont_mul(&mm, y, v, aa); x = mp_sub(x, x, y); }
+ if (MP_NEGP(x)) x = mp_add(x, x, n);
+ if (!MP_ZEROP(x)) { rc = PGEN_FAIL; goto end; }
+
+ /* Grantham's Frobenius test is that, also, %$V_k(a, b) v = \equiv 2 b$%
+ * if %$n$% is prime and %$(\Delta | n) = -1$%, or %$v \equiv 2$% if
+ * %$(\Delta | n) = +1$%.
+ */
+ if (MP_ODDP(v)) v = mp_add(v, v, n);
+ v = mp_lsr(v, v, 1);
+ if (!MP_EQ(v, e == +1 ? mm.r : bb)) { rc = PGEN_FAIL; goto end; }
+
+ /* Looks like we made it. */
+ rc = PGEN_PASS;
+end:
+ mp_drop(v); mp_drop(w); mp_drop(aa); mp_drop(bb); mp_drop(bi);
+ mp_drop(k); mp_drop(x); mp_drop(y); mp_drop(z);
+ mpmont_destroy(&mm);
+ return (rc);
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <mLib/testrig.h>
+
+#include "mptext.h"
+
+static int verify(dstr *v)
+{
+ mp *n = *(mp **)v[0].buf;
+ int a = *(int *)v[1].buf, b = *(int *)v[2].buf, xrc = *(int *)v[3].buf, rc;
+ int ok = 1;
+
+ rc = pgen_granfrob(n, a, b);
+ if (rc != xrc) {
+ fputs("\n*** pgen_granfrob failed", stdout);
+ fputs("\nn = ", stdout); mp_writefile(n, stdout, 10);
+ printf("\na = %d", a);
+ printf("\nb = %d", a);
+ printf("\nexp rc = %d", xrc);
+ printf("\ncalc rc = %d\n", rc);
+ ok = 0;
+ }
+
+ mp_drop(n);
+ assert(mparena_count(MPARENA_GLOBAL) == 0);
+ return (ok);
+}
+
+static test_chunk tests[] = {
+ { "pgen-granfrob", verify,
+ { &type_mp, &type_int, &type_int, &type_int, 0 } },
+ { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+ sub_init();
+ test_run(argc, argv, tests, SRCDIR "/t/pgen");
+ return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
* @grand *gr@ = a random number source
*
* Returns: Nonzero if @p@ is really prime.
+ *
+ * Use: Checks the primality of @p@. If @p@ is prime, then this
+ * function returns nonzero; if @p@ is really composite then it
+ * %%\emph{probably}%% returns zero, but might not.
+ *
+ * Currently, this function uses the Baillie--PSW test, which
+ * combines a single Miller--Rabin test with witness 2 with a
+ * single Frobenius test with parameters chosen using
+ * Selfridge's `Method A'. No composites are known which pass
+ * this test, though it's conjectured that infinitely many
+ * exist.
*/
int pgen_primep(mp *p, grand *gr)
{
- int i;
rabin r;
- mp *x = MP_NEW;
+ int rc;
if (MP_NEGP(p)) return (0);
switch (pfilt_smallfactor(p)) {
case PGEN_DONE: return (1);
case PGEN_FAIL: return (0);
}
- rabin_create(&r, p);
- for (i = 32; i; i--) {
- x = mprand_range(x, p, gr, 0);
- if (rabin_rtest(&r, x) == PGEN_FAIL)
- break;
- }
- MP_DROP(x);
- rabin_destroy(&r);
- return (!i);
+ rabin_create(&r, p); rc = rabin_test(&r, MP_TWO); rabin_destroy(&r);
+ if (rc == PGEN_FAIL) return (0);
+ rc = pgen_granfrob(p, 0, 0); if (rc == PGEN_FAIL) return (0);
+ return (1);
}
/*----- Test rig ----------------------------------------------------------*/
unsigned /*steps*/, pgen_proc */*step*/, void */*sctx*/,
unsigned /*tests*/, pgen_proc */*test*/, void */*tctx*/);
+/* --- @pgen_granfrob@ --- *
+ *
+ * Arguments: @mp *n@ = an integer to test
+ * @int a, b@ = coefficients; if @a@ is zero then choose
+ * automatically
+ *
+ * Returns: One of the @PGEN_...@ codes.
+ *
+ * Use: Performs a quadratic version of Grantham's Frobenius
+ * primality test, which is a simple extension of the standard
+ * Lucas test.
+ *
+ * If %$a^2 - 4 b$% is a perfect square then the test can't
+ * work; this function returns @PGEN_ABORT@ under these
+ * circumstances.
+ *
+ * If @a@ is zero on entry, then the function will choose
+ * suitable parameters deterministically -- i.e., it always
+ * chooses the same parameters for a given %$n$%.
+ */
+
+extern int pgen_granfrob(mp */*n*/, int /*a*/, int /*b*/);
+
/* --- @pgen_primep@ --- *
*
* Arguments: @mp *p@ = a number to check
166359567317705838255275971708060308423814413741683015010175247351623188739655446196925981468626681882384215574706593049022467680136399439302347043107836749816290369600677730213469006507173065402294688841278559283358390567733443050775707749725690534182003442070447739085348456478911335969765393755383551520173 166359567317705838255275971708060308423814413741683015010175247351623188739655446196925981468626681882384215574706593049022467680136399439302347043107836749816290369600677730213469006507173065402294688841278559283358390567733443050775707749725690534182003442070447739085348456478911335969765393755383551520257;
}
+pgen-granfrob {
+ 5 0 0 -1;
+ 7 0 0 4;
+ 15 0 0 3;
+ 5777 1 -1 4; # pseudoprime
+ 40301809 0 0 4;
+ 86059163416987297647409667483582114939806237974424324409828198660056356336227 1 5 4;
+ 102508420970861015999300753620309481186457893679971500520427161277511389396803 1 5 4;
+ 72291866454056552194087337607224612505157525245486245416393486917859196707519 1 5 4;
+ 72291866454056552194087337607224612505157525245486265416393486917859196707519 1 5 3;
+
+ ## A large Frobenius pseudoprime: call the first number p_1; then p_2 = 31
+ ## (p_1 + 1) - 1 and p_3 = 43 (p_1 + 1) - 1. These three are all prime.
+ ## Their product is a strong Lucas, and Frobenius, pseudoprime.
+ ##
+ ## See `Prime and Prejudice' by Martin R. Albrecht, Jake Massimo, Kenneth
+ ## G. Paterson, and Juraj Somorovsky.
+ 3690125385954346893658786222051913500627130245213169388019826598097107079718295481926241398412699320815932808015860263240282855670239765686869973444864115322609857375876438922226372746215468824202413623127 0 0 4;
+ 114393886964584753703422372883609318519441037601608251028614624541010319471267159939713483350793678945293917048491668160448768525777432736292969176790787575000905578652169606589017555132679533550274822316967 0 0 4;
+ 158675391596036916427327807548232280526966600544166283684852543718175604427886705722828380131746070795085110744681991319332162793820309924535408858129156958872223867162686873655734028087265159440703785794503 0 0 4;
+ 66981291792500223036804182765508448534715465524671325885174850970812009004775815201151227900130153990294748113034471984909912807896550069799856170439734910206802409847773026240559371480115711600866989845251707737806461503879250232804362190067578216069266197879151809743235261582813331022213587929425243163096486125825510076936556242805690400001899138503900919499414951069309064408305196756524628693684938044145785145327821174180933033293089394794328963673467918652042794300291355500468079109432376296868174257674548727592142782202898031102246775544402811199608266683925072825828225074019194302318324623049819212337927 0 0 4;
+}
+
primep {
-5 0;
-1 0;
4 0;
40301809 1;
40301811 0;
+
+ ## A small Lucas pseudoprime: 5777 = 53*109.
+ 5777 0;
+
+ ## A large strong pseudoprime: this is the product of
+ ##
+ ## p_1 = 142445387161415482404826365418175962266689133006163
+ ## p_2 = 5840260873618034778597880982145214452934254453252643
+ ## p_3 = 14386984103302963722887462907235772188935602433622363
+ ##
+ ## See `Prime and Prejudice' by Martin R. Albrecht, Jake Massimo, Kenneth
+ ## G. Paterson, and Juraj Somorovsky.
+ 142445387161415482404826365418175962266689133006163 1;
+ 5840260873618034778597880982145214452934254453252643 1;
+ 14386984103302963722887462907235772188935602433622363 1;
+ 11968794224604718293549908104759518204343930652759288592987578098131927050572705181539873293848476235393230314654912729920657864630317971562727057595285667 0;
+
+ ## A large Lucas pseudoprime: call the first number p_1; then p_2 = 31 (p_1
+ ## + 1) - 1 and p_3 = 43 (p_1 + 1) - 1. These three are all prime. Their
+ ## product is a strong Lucas pseudoprime.
+ 3690125385954346893658786222051913500627130245213169388019826598097107079718295481926241398412699320815932808015860263240282855670239765686869973444864115322609857375876438922226372746215468824202413623127 1;
+ 114393886964584753703422372883609318519441037601608251028614624541010319471267159939713483350793678945293917048491668160448768525777432736292969176790787575000905578652169606589017555132679533550274822316967 1;
+ 158675391596036916427327807548232280526966600544166283684852543718175604427886705722828380131746070795085110744681991319332162793820309924535408858129156958872223867162686873655734028087265159440703785794503 1;
+ 66981291792500223036804182765508448534715465524671325885174850970812009004775815201151227900130153990294748113034471984909912807896550069799856170439734910206802409847773026240559371480115711600866989845251707737806461503879250232804362190067578216069266197879151809743235261582813331022213587929425243163096486125825510076936556242805690400001899138503900919499414951069309064408305196756524628693684938044145785145327821174180933033293089394794328963673467918652042794300291355500468079109432376296868174257674548727592142782202898031102246775544402811199608266683925072825828225074019194302318324623049819212337927 0;
}
primeiter {
--- /dev/null
+/getdate.h
+/getdate.y
## Remember passphrases for limited periods of time.
bin_PROGRAMS += pixie
pixie_SOURCES = pixie.c
-pixie_LDADD = $(UTILS_LIBS) $(PIXIE_LIBS) $(LOGLIBS)
+pixie_LDADD = $(top_builddir)/base/libbase.la
+pixie_LDADD += $(top_builddir)/key/libkey.la
+pixie_LDADD += $(mLib_LIBS) $(PIXIE_LIBS) $(LOGLIBS)
dist_man_MANS += pixie.1
EXTRA_DIST += xpixie
.B cipher
and
.B mac
-attributes.
+attributes. Run
+.B catcrypt show cipher
+for a list of supported symmetric encryption algorithms; the default
+.I cipher
+is
+.BR blowfish-cbc .
This is the default transform.
.TP
+.B aead
+Use an `authenticated encryption with additional data' (AEAD) scheme.
+The specific scheme is named by the
+.B cipher
+attribute. Run
+.B catcrypt show aead
+for a list of supported AEAD schemes; the default is
+.BR chacha20-poly1305 .
+.TP
.B naclbox
Use Salsa20 or ChaCha and Poly1305 to secure the bulk data.
This is nearly the same as the NaCl
.BR chacha8 ;
the default is
.BR salsa20 .
+Nowadays, this is equivalent to the
+.B aead
+transform, using
+.IB cipher -naclbox
+as the cipher.
.PP
As well as the KEM itself, a number of supporting algorithms are used.
These are taken from appropriately named attributes on the key or,
.I bulk
in the
.I kemalgspec
-is used; if that it absent, then the default of
-.B blowfish-cbc
-is used. Run
-.B catcrypt show cipher
-for a list of supported symmetric encryption algorithms.
+is used; if that it absent, then the default depends on the bulk
+transform.
.TP
.B hash
This is the hash function used to distil entropy from the shared secret
attribute.
.TP
.B cipher
-The symmetric encryption algorithms which can be used in a
+The symmetric encryption algorithms which can be named in a
key-encapsulation key's
.B cipher
-attribute.
+attribute when using the
+.B gencomp
+bulk transform.
.TP
.B mac
-The message authentication algorithms which can be used in a
+The message authentication algorithms which can be named in a
key-encapsulation key's
.B mac
attribute.
.TP
.B sig
-The signature algorithms which can be used in a signing key's
+The signature algorithms which can be named in a signing key's
.B sig
attribute.
.TP
.B hash
-The hash functions which can be used in a key's
+The hash functions which can be named in a key's
.B hash
attribute.
.TP
#include "key.h"
#include "cc.h"
+#include "gaead.h"
#include "ectab.h"
#include "ptab.h"
enctab[i].name, enctab[i].name) \
LI("Symmetric encryption algorithms", cipher, \
gciphertab[i], gciphertab[i]->name) \
+ LI("Authenticated encryption schemes", aead, \
+ gaeadtab[i], gaeadtab[i]->name) \
LI("Hash functions", hash, \
ghashtab[i], ghashtab[i]->name) \
LI("Message authentication codes", mac, \
#include <mLib/report.h>
#include <mLib/sub.h>
+#include "gaead.h"
#include "mprand.h"
#include "rand.h"
#include "rmd160.h"
#include "blowfish-cbc.h"
+#include "chacha20-poly1305.h"
#include "poly1305.h"
#include "salsa20.h"
#include "chacha.h"
/*----- Bulk crypto -------------------------------------------------------*/
-/* --- NaCl `secretbox' --- */
+/* --- Authenticated encryption schemes --- */
-typedef struct naclbox_encctx {
+typedef struct aead_encctx {
bulk b;
- const gccipher *cc;
- gcipher *c;
-} naclbox_encctx;
+ const gcaead *aec;
+ gaead_key *key;
+ union { gaead_enc *enc; gaead_dec *dec; } ed;
+ octet *t;
+ size_t nsz, tsz;
+} aead_encctx;
-static bulk *naclbox_init(key *k, const char *calg, const char *halg)
+static bulk *aead_internalinit(key *k, const gcaead *aec)
{
- naclbox_encctx *ctx = CREATE(naclbox_encctx);
- dstr t = DSTR_INIT;
+ aead_encctx *ctx = CREATE(aead_encctx);
+
+ ctx->key = 0;
+ ctx->aec = aec;
+ if ((ctx->nsz = keysz_pad(4, aec->noncesz)) == 0)
+ die(EXIT_FAILURE, "no suitable nonce size for `%s'", aec->name);
+ ctx->tsz = keysz(0, ctx->aec->tagsz);
+
+ return (&ctx->b);
+}
+
+static bulk *aead_init(key *k, const char *calg, const char *halg)
+{
+ const gcaead *aec;
const char *q;
+ dstr t = DSTR_INIT;
key_fulltag(k, &t);
if ((q = key_getattr(0, k, "cipher")) != 0) calg = q;
- if (!calg || strcmp(calg, "salsa20") == 0) ctx->cc = &salsa20;
- else if (strcmp(calg, "salsa20/12") == 0) ctx->cc = &salsa2012;
- else if (strcmp(calg, "salsa20/8") == 0) ctx->cc = &salsa208;
- else if (strcmp(calg, "chacha20") == 0) ctx->cc = &chacha20;
- else if (strcmp(calg, "chacha12") == 0) ctx->cc = &chacha12;
- else if (strcmp(calg, "chacha8") == 0) ctx->cc = &chacha8;
- else {
- die(EXIT_FAILURE,
- "unknown or inappropriate encryption scheme `%s' in key `%s'",
+ if (!calg) aec = &chacha20_poly1305;
+ else if ((aec = gaead_byname(calg)) == 0)
+ die(EXIT_FAILURE, "AEAD scheme `%s' not found in key `%s'",
calg, t.buf);
- }
dstr_destroy(&t);
- return (&ctx->b);
+ return (aead_internalinit(k, aec));
}
-static int naclbox_setup(bulk *b, gcipher *cx)
+static int aead_commonsetup(aead_encctx *ctx, gcipher *cx)
{
- naclbox_encctx *ctx = (naclbox_encctx *)b;
- octet k[SALSA20_KEYSZ];
+ size_t ksz, n;
- GC_ENCRYPT(cx, 0, k, sizeof(k));
- ctx->c = GC_INIT(ctx->cc, k, sizeof(k));
+ n = ksz = keysz(0, ctx->aec->keysz);
+ if (n < ctx->nsz) n = ctx->nsz;
+ if (n < ctx->tsz) n = ctx->tsz;
+ ctx->t = xmalloc(n);
+
+ GC_ENCRYPT(cx, 0, ctx->t, ksz);
+ ctx->key = GAEAD_KEY(ctx->aec, ctx->t, ksz);
return (0);
}
-static size_t naclbox_overhead(bulk *b) { return (POLY1305_TAGSZ); }
+static size_t aead_overhead(bulk *b)
+ { aead_encctx *ctx = (aead_encctx *)b; return (ctx->aec->ohd + ctx->tsz); }
-static void naclbox_destroy(bulk *b)
+static void aead_commondestroy(aead_encctx *ctx)
{
- naclbox_encctx *ctx = (naclbox_encctx *)b;
-
- GC_DESTROY(ctx->c);
+ if (ctx->key) GAEAD_DESTROY(ctx->key);
+ xfree(ctx->t);
DESTROY(ctx);
}
-static const char *naclbox_encdoit(bulk *b, uint32 seq, buf *bb,
- const void *p, size_t sz)
+static int aead_encsetup(bulk *b, gcipher *cx)
{
- naclbox_encctx *ctx = (naclbox_encctx *)b;
- octet t[32];
- poly1305_key ak;
- poly1305_ctx a;
- octet *tag, *ct;
+ aead_encctx *ctx = (aead_encctx *)b;
+ ctx->ed.enc = 0; return (aead_commonsetup(ctx, cx));
+}
- STORE32(t, seq); STORE32(t + 4, 0); GC_SETIV(ctx->c, t);
- GC_ENCRYPT(ctx->c, 0, t, POLY1305_KEYSZ + POLY1305_MASKSZ);
- poly1305_keyinit(&ak, t, POLY1305_KEYSZ);
- poly1305_macinit(&a, &ak, t + POLY1305_KEYSZ);
+static const char *aead_encdoit(bulk *b, uint32 seq, buf *bb,
+ const void *p, size_t sz)
+{
+ aead_encctx *ctx = (aead_encctx *)b;
+ octet *t;
+ int rc;
- tag = buf_get(bb, POLY1305_TAGSZ); assert(tag);
- ct = buf_get(bb, sz); assert(ct);
- GC_ENCRYPT(ctx->c, p, ct, sz);
- poly1305_hash(&a, ct, sz);
- poly1305_done(&a, tag);
+ memset(ctx->t + 4, 0, ctx->nsz - 4); STORE32_B(ctx->t, seq);
+ if (!ctx->ed.enc)
+ ctx->ed.enc = GAEAD_ENC(ctx->key, ctx->t, ctx->nsz, 0, sz, ctx->tsz);
+ else
+ GAEAD_REINIT(ctx->ed.enc, ctx->t, ctx->nsz, 0, sz, ctx->tsz);
+ t = buf_get(bb, ctx->tsz); assert(t);
+ rc = GAEAD_ENCRYPT(ctx->ed.enc, p, sz, bb); assert(rc >= 0);
+ rc = GAEAD_DONE(ctx->ed.enc, 0, bb, t, ctx->tsz); assert(rc >= 0);
return (0);
}
-static const char *naclbox_decdoit(bulk *b, uint32 seq, buf *bb,
- const void *p, size_t sz)
+static void aead_encdestroy(bulk *b)
+{
+ aead_encctx *ctx = (aead_encctx *)b;
+ if (ctx->ed.enc) GAEAD_DESTROY(ctx->ed.enc);
+ aead_commondestroy(ctx);
+}
+
+static int aead_decsetup(bulk *b, gcipher *cx)
{
- naclbox_encctx *ctx = (naclbox_encctx *)b;
+ aead_encctx *ctx = (aead_encctx *)b;
+ ctx->ed.dec = 0; return (aead_commonsetup(ctx, cx));
+}
+
+static const char *aead_decdoit(bulk *b, uint32 seq, buf *bb,
+ const void *p, size_t sz)
+{
+ aead_encctx *ctx = (aead_encctx *)b;
buf bin;
- octet t[32];
- poly1305_key ak;
- poly1305_ctx a;
- octet *tag, *ct, *pt;
+ const octet *t;
+ int rc;
- STORE32(t, seq); STORE32(t + 4, 0); GC_SETIV(ctx->c, t);
- GC_ENCRYPT(ctx->c, 0, t, POLY1305_KEYSZ + POLY1305_MASKSZ);
- poly1305_keyinit(&ak, t, POLY1305_KEYSZ);
- poly1305_macinit(&a, &ak, t + POLY1305_KEYSZ);
+ memset(ctx->t + 4, 0, ctx->nsz - 4); STORE32_B(ctx->t, seq);
+ if (!ctx->ed.dec)
+ ctx->ed.dec = GAEAD_DEC(ctx->key, ctx->t, ctx->nsz, 0, sz, ctx->tsz);
+ else
+ GAEAD_REINIT(ctx->ed.enc, ctx->t, ctx->nsz, 0, sz, ctx->tsz);
buf_init(&bin, (/*unconst*/ void *)p, sz);
- if ((tag = buf_get(&bin, POLY1305_TAGSZ)) == 0) return ("no tag");
- ct = BCUR(&bin); sz = BLEFT(&bin);
- poly1305_hash(&a, ct, sz);
- poly1305_done(&a, t);
- if (!ct_memeq(t, tag, POLY1305_TAGSZ)) return ("authentication failure");
- pt = buf_get(bb, sz); assert(pt);
- GC_DECRYPT(ctx->c, ct, pt, sz);
+ t = buf_get(&bin, ctx->tsz); if (!t) return ("no tag");
+ rc = GAEAD_DECRYPT(ctx->ed.dec, BCUR(&bin), BLEFT(&bin), bb);
+ assert(rc >= 0);
+ rc = GAEAD_DONE(ctx->ed.dec, 0, bb, t, ctx->tsz); assert(rc >= 0);
+ if (!rc) return ("authentication failure");
return (0);
}
+static void aead_decdestroy(bulk *b)
+{
+ aead_encctx *ctx = (aead_encctx *)b;
+ if (ctx->ed.dec) GAEAD_DESTROY(ctx->ed.dec);
+ aead_commondestroy(ctx);
+}
+
+static const struct bulkops aead_encops = {
+ aead_init, aead_encsetup, aead_overhead,
+ aead_encdoit, aead_encdestroy
+}, aead_decops = {
+ aead_init, aead_decsetup, aead_overhead,
+ aead_decdoit, aead_decdestroy
+};
+
+/* --- NaCl `secretbox' in terms of AEAD --- */
+
+static bulk *naclbox_init(key *k, const char *calg, const char *halg)
+{
+ const gcaead *aec;
+ dstr t = DSTR_INIT;
+ const char *q;
+
+ key_fulltag(k, &t);
+
+ if ((q = key_getattr(0, k, "cipher")) != 0) calg = q;
+ if (!calg || strcmp(calg, "salsa20") == 0) aec = &salsa20_naclbox;
+ else if (strcmp(calg, "salsa20/12") == 0) aec = &salsa2012_naclbox;
+ else if (strcmp(calg, "salsa20/8") == 0) aec = &salsa208_naclbox;
+ else if (strcmp(calg, "chacha20") == 0) aec = &chacha20_naclbox;
+ else if (strcmp(calg, "chacha12") == 0) aec = &chacha12_naclbox;
+ else if (strcmp(calg, "chacha8") == 0) aec = &chacha8_naclbox;
+ else {
+ die(EXIT_FAILURE,
+ "unknown or inappropriate encryption scheme `%s' in key `%s'",
+ calg, t.buf);
+ }
+
+ dstr_destroy(&t);
+ return (aead_internalinit(k, aec));
+}
+
static const bulkops naclbox_encops = {
- naclbox_init, naclbox_setup, naclbox_overhead,
- naclbox_encdoit, naclbox_destroy
+ naclbox_init, aead_encsetup, aead_overhead,
+ aead_encdoit, aead_encdestroy
}, naclbox_decops = {
- naclbox_init, naclbox_setup, naclbox_overhead,
- naclbox_decdoit, naclbox_destroy
+ naclbox_init, aead_decsetup, aead_overhead,
+ aead_decdoit, aead_decdestroy
};
/* --- Generic composition --- */
const struct bulktab bulktab[] = {
{ "gencomp", &gencomp_encops, &gencomp_decops },
{ "naclbox", &naclbox_encops, &naclbox_decops },
+ { "aead", &aead_encops, &aead_decops },
{ 0, 0, 0 }
};
#include <sys/time.h>
#include <unistd.h>
+#ifdef HAVE_LINUX_PERF_EVENT_H
+# include <linux/perf_event.h>
+# include <asm/unistd.h>
+#endif
+
#include <mLib/alloc.h>
+#include <mLib/bits.h>
#include <mLib/dstr.h>
#include <mLib/mdwopt.h>
#include <mLib/quis.h>
#include "ed448.h"
#include "cc.h"
+#include "gaead.h"
#include "gcipher.h"
#include "ghash.h"
#include "gmac.h"
typedef struct opts {
const char *name; /* Pre-configured named thing */
+ const char *opwhat; /* What to call operations */
unsigned fbits; /* Field size bits */
unsigned gbits; /* Group size bits */
unsigned n; /* Number of factors */
unsigned i; /* Number of intervals (or zero) */
+ unsigned k; /* Main loop batch size */
+ unsigned long sc; /* Scale factor */
double t; /* Time for each interval (secs) */
mp *e; /* Public exponent */
unsigned f; /* Flags */
die(1, "must specify encryption scheme name");
if ((c->c = gcipher_byname(o->name)) == 0)
die(1, "encryption scheme `%s' not known", o->name);
- c->ksz = keysz(o->gbits/8, c->c->keysz);
+ c->ksz = keysz(o->fbits/8, c->c->keysz);
+ if (o->fbits%8 || (o->fbits && c->ksz != o->fbits/8))
+ die(1, "bad key size %u for %s", o->fbits, o->name);
c->k = xmalloc(c->ksz);
rand_get(RAND_GLOBAL, c->k, c->ksz);
return (c);
die(1, "must specify encryption scheme name");
if ((cc = gcipher_byname(o->name)) == 0)
die(1, "encryption scheme `%s' not known", o->name);
- ksz = keysz(0, cc->keysz);
+ ksz = keysz(o->fbits/8, cc->keysz);
+ if (o->fbits%8 || (o->fbits && ksz != o->fbits/8))
+ die(1, "bad key size %u for %s", o->fbits, o->name);
k = xmalloc(ksz);
rand_get(RAND_GLOBAL, k, ksz);
c->c = GC_INIT(cc, k, ksz);
xfree(k);
c->sz = o->gbits ? o->gbits : 65536;
c->n = o->n ? o->n : 16;
+ o->opwhat = "byte"; o->sc = c->n*c->sz;
c->m = xmalloc(c->sz);
return (c);
}
GC_ENCRYPT(c->c, c->m, c->m, c->sz);
}
+/* --- Authenticated encryption --- */
+
+typedef struct aeadsetup_ctx {
+ const gcaead *aec;
+ octet *k; size_t ksz;
+ octet *n; size_t nsz;
+ size_t tsz;
+} aeadsetup_ctx;
+
+static void *aeadsetup_init(opts *o)
+{
+ aeadsetup_ctx *c = CREATE(aeadsetup_ctx);
+ if (!o->name)
+ die(1, "must specify encryption scheme name");
+ if ((c->aec = gaead_byname(o->name)) == 0)
+ die(1, "aead scheme `%s' not known", o->name);
+ c->ksz = keysz(o->fbits/8, c->aec->keysz);
+ c->nsz = keysz_pad(o->gbits/8, c->aec->noncesz);
+ c->tsz = keysz(0, c->aec->tagsz);
+ if (o->fbits%8 || (o->fbits && c->ksz != o->fbits/8))
+ die(1, "bad key size %u for %s", o->fbits, o->name);
+ if (o->gbits%8 || (o->gbits && c->nsz != o->gbits/8))
+ die(1, "bad nonce size %u for %s", o->gbits, o->name);
+ c->k = xmalloc(c->ksz); rand_get(RAND_GLOBAL, c->k, c->ksz);
+ c->n = xmalloc(c->nsz); rand_get(RAND_GLOBAL, c->n, c->nsz);
+ return (c);
+}
+
+static void aeadsetup_run(void *cc)
+{
+ aeadsetup_ctx *c = cc;
+ gaead_key *k = GAEAD_KEY(c->aec, c->k, c->ksz);
+ gaead_enc *e = GAEAD_ENC(k, c->n, c->nsz, 0, 0, c->tsz);
+ GAEAD_DESTROY(e); GAEAD_DESTROY(k);
+}
+
+typedef struct aeadenc_ctx {
+ gaead_enc *enc;
+ octet *n; size_t nsz;
+ octet *p, *q; size_t sz; size_t nn;
+ size_t tsz;
+} aeadenc_ctx;
+
+static void *aeadenc_init(opts *o)
+{
+ aeadenc_ctx *c = CREATE(aeadenc_ctx);
+ const gcaead *aec;
+ gaead_key *key;
+ octet *k; size_t ksz;
+
+ if (!o->name)
+ die(1, "must specify encryption scheme name");
+ if ((aec = gaead_byname(o->name)) == 0)
+ die(1, "aead scheme `%s' not known", o->name);
+ c->sz = o->gbits ? o->gbits : 65536;
+ c->nn = o->n ? o->n : 16;
+ ksz = keysz(o->fbits/8, aec->keysz);
+ c->nsz = keysz(0, aec->noncesz);
+ c->tsz = keysz(0, aec->tagsz);
+ if (o->fbits%8 || (o->fbits && ksz != o->fbits/8))
+ die(1, "bad key size %u for %s", o->fbits, o->name);
+
+ k = xmalloc(ksz); rand_get(RAND_GLOBAL, k, ksz);
+ c->n = xmalloc(c->nsz); rand_get(RAND_GLOBAL, c->n, c->nsz);
+ c->p = xmalloc(c->sz); c->q = xmalloc(c->sz + aec->bufsz);
+
+ key = GAEAD_KEY(aec, k, ksz);
+ c->enc = GAEAD_ENC(key, c->n, c->nsz, 0, 0, c->tsz);
+ GAEAD_DESTROY(key); xfree(k);
+
+ o->opwhat = "byte"; o->sc = c->nn*c->sz;
+ return (c);
+}
+
+static void aeadaad_run(void *cc)
+{
+ aeadenc_ctx *c = cc;
+ gaead_aad *a;
+ size_t i;
+
+ GAEAD_REINIT(c->enc, c->n, c->nsz, c->nn*c->sz, 0, c->tsz);
+ a = GAEAD_AAD(c->enc);
+ for (i = 0; i < c->nn; i++) GAEAD_HASH(a, c->p, c->sz);
+ GAEAD_DESTROY(a);
+}
+
+static void aeadenc_run(void *cc)
+{
+ aeadenc_ctx *c = cc;
+ buf b;
+ size_t i;
+
+ GAEAD_REINIT(c->enc, c->n, c->nsz, 0, c->nn*c->sz, c->tsz);
+ for (i = 0; i < c->nn; i++) {
+ buf_init(&b, c->q, c->sz + c->enc->ops->c->bufsz);
+ GAEAD_ENCRYPT(c->enc, c->p, c->sz, &b);
+ }
+}
+
/* --- Hashing --- */
typedef struct hash_ctx {
die(1, "hash function `%s' not known", o->name);
c->sz = o->gbits ? o->gbits : 65536;
c->n = o->n ? o->n : 16;
+ o->opwhat = "byte"; o->sc = c->n*c->sz;
c->m = xmalloc(c->sz);
return (c);
}
rand_get(RAND_GLOBAL, c->s, sizeof(c->s));
c->sz = o->gbits ? o->gbits : 65536;
c->n = o->n ? o->n : 16;
+ o->opwhat = "byte"; o->sc = c->n*c->sz;
c->m = xmalloc(c->sz);
return (c);
}
{ "ed448-vrf", ed448_vrfinit, ed448_vrfrun },
{ "ksched", ksched_init, ksched_run },
{ "enc", enc_init, enc_run },
+ { "aead-setup", aeadsetup_init, aeadsetup_run },
+ { "aead-aad", aeadenc_init, aeadaad_run },
+ { "aead-enc", aeadenc_init, aeadenc_run },
{ "hash", hash_init, hash_run },
{ "poly1305", poly1305_jobinit, poly1305_jobrun },
{ 0, 0, 0 }
};
+/*----- Cycle counting ----------------------------------------------------*/
+
+typedef kludge64 cycles;
+static int cyclecount_active_p = 0;
+
+#if defined(__GNUC__) && (CPUFAM_X86 || CPUFAM_AMD64)
+
+static void init_cyclecount(void) { cyclecount_active_p = 1; }
+
+static cycles cyclecount(void)
+{
+ uint32 lo, hi;
+ kludge64 cy;
+
+ __asm__("rdtsc" : "=a"(lo), "=d"(hi));
+ SET64(cy, hi, lo);
+ return cy;
+}
+
+#elif defined(HAVE_LINUX_PERF_EVENT_H) && defined(HAVE_UINT64)
+
+static int perf_fd = -1;
+
+static void init_cyclecount(void)
+{
+ struct perf_event_attr attr = { 0 };
+
+ attr.type = PERF_TYPE_HARDWARE;
+ attr.size = sizeof(attr);
+ attr.config = PERF_COUNT_HW_CPU_CYCLES;
+ attr.disabled = 0;
+ attr.exclude_kernel = 1;
+ attr.exclude_hv = 1;
+
+ if ((perf_fd = syscall(__NR_perf_event_open, &attr, 0, -1, -1, 0)) < 0)
+ moan("failed to open perf event: %s", strerror(errno));
+ else
+ cyclecount_active_p = 1;
+}
+
+static cycles cyclecount(void)
+{
+ kludge64 cy;
+ ssize_t n;
+
+ if (!cyclecount_active_p)
+ goto fail;
+ else if ((n = read(perf_fd, &cy.i, sizeof(cy.i))) != sizeof(cy.i)) {
+ if (n < 0) moan("error reading perf event: %s", strerror(errno));
+ else moan("unexpected short read from perf event");
+ cyclecount_active_p = 0; close(perf_fd); perf_fd = -1;
+ goto fail;
+ }
+end:
+ return (cy);
+fail:
+ SET64(cy, 0, 0);
+ goto end;
+}
+
+#else
+
+static void init_cyclecount(void) { cyclecount_active_p = 0; }
+static cycles cyclecount(void) { kludge64 cy; SET64(cy, 0, 0); return (cy); }
+
+#endif
+
/*----- Main code ---------------------------------------------------------*/
void version(FILE *fp)
-l, --list [ITEM...] List all the various names of things.\n\
\n\
-C, --name=NAME Select curve/DH-group/enc/hash name.\n\
--b, --field-bits Field size for g-prime and rsa.\n\
+-b, --field-bits Field size for g-prime and rsa;\n\
+ key bits for ksched, enc, aead-setup, aead-enc.\n\
-q, --no-check Don't check field/group for validity.\n\
--B, --group-bits Group size for g-prime; key size for ksched;\n\
- data size for enc and hash.\n\
+-B, --group-bits Group size for g-prime; nonce bits for aead-setup;\n\
+ data size for enc, aead-aad, aead-enc, and hash.\n\
-n, --factors=COUNT Number of factors for {exp,mul}-sim;\n\
- inner iterations for enc and hash.\n\
+ inner iters for enc, aead-aad, aead-enc, hash.\n\
-i, --intervals=COUNT Number of intervals to run for. [0; forever]\n\
+-k, --batch=COUNT Number of operations to batch between timer checks.\n\
-t, --time=TIME Length of an interval in seconds. [1]\n\
");
}
ptab[i].name, ptab[i].name) \
LI("Encryption algorithms", cipher, \
gciphertab[i], gciphertab[i]->name) \
+ LI("Authenticated encryption schemes", aead, \
+ gaeadtab[i], gaeadtab[i]->name) \
LI("Hash functions", hash, \
ghashtab[i], ghashtab[i]->name)
opts o = { 0 };
const jobops *j;
struct timeval tv_next, tv_now;
- double t, ttot;
- unsigned n;
+ double t, ttot, cy, cytot;
+ unsigned n, k;
unsigned long ii;
- clock_t c_start, c_stop;
+ clock_t c0, c1;
+ kludge64 cy0, cy1, cydiff;
double itot;
void *p;
ego(argv[0]);
- o.t = 1;
+ o.t = 1; o.k = 1; o.sc = 1; o.opwhat = "op";
for (;;) {
static const struct option opts[] = {
{ "help", 0, 0, 'h' },
{ "group-bits", OPTF_ARGREQ, 0, 'B' },
{ "factors", OPTF_ARGREQ, 0, 'n' },
{ "intervals", OPTF_ARGREQ, 0, 'i' },
+ { "batch", OPTF_ARGREQ, 0, 'k' },
{ "public-exponent", OPTF_ARGREQ, 0, 'e' },
{ "time", OPTF_ARGREQ, 0, 't' },
{ "no-check", 0, 0, 'q' },
{ 0, 0, 0, 0 }
};
- i = mdwopt(argc, argv, "hvulC:b:B:n:i:e:t:q", opts, 0, 0, 0);
+ i = mdwopt(argc, argv, "hvulC:b:B:n:i:k:e:t:q", opts, 0, 0, 0);
if (i < 0) break;
switch (i) {
case 'h': help(stdout); exit(0);
break;
case 'i': o.i = uarg("interval count", optarg); break;
case 't': o.t = farg("interval length", optarg); break;
+ case 'k': o.k = uarg("batch size", optarg); break;
case 'q': o.f |= OF_NOCHECK; break;
default: usage(stderr); exit(1);
}
p = j->init(&o);
n = 0;
- ttot = itot = 0;
+ ttot = itot = 0; cytot = 0; init_cyclecount();
gettimeofday(&tv_now, 0);
do {
tv_addl(&tv_next, &tv_now, o.t, fmod(o.t * MILLION, MILLION));
ii = 0;
- c_start = clock();
+ c0 = clock(); cy0 = cyclecount();
do {
- j->run(p);
- ii++;
+ for (k = 0; k < o.k; k++) { j->run(p); }
+ ii += k;
gettimeofday(&tv_now, 0);
} while (TV_CMP(&tv_now, <, &tv_next));
- c_stop = clock();
- t = (double)(c_stop - c_start)/CLOCKS_PER_SEC;
- itot += ii;
- ttot += t;
- printf("%5u: did = %5lu; /sec = %5f; avg /sec = %5f\n",
+ cy1 = cyclecount(); c1 = clock();
+ t = (double)(c1 - c0)/CLOCKS_PER_SEC;
+ itot += ii; ttot += t;
+ printf("%5u: did = %5lu; /sec = %5f; avg /sec = %5f",
n, ii, ii/t, itot/ttot);
+ if (cyclecount_active_p) {
+ SUB64(cydiff, cy1, cy0); cy = LO64(cydiff) + ldexp(HI64(cydiff), 32);
+ cytot += cy;
+ printf(" (cy/%s = %3f; avg cy/%s = %3f)",
+ o.opwhat, cy/ii/o.sc, o.opwhat, cytot/itot/o.sc);
+ }
+ putchar('\n');
fflush(stdout);
n++;
} while (!o.i || n < o.i);
group *g;
dh_infofromdata(&dp, pe->data);
g = group_prime(&dp);
- if (mp_bits(dp.p) > 2048 &&
+ if (mp_bits(dp.p) > 3072 &&
(!argv[1] || strcmp(argv[1], "keen") != 0)) {
printf(" [%s skipped]", pe->name);
fflush(stdout);
-modes/
+/modes/
+/modes.am
+/stubs.am
+/stubs.gen-stamp
+
+/t/salsa20
+/t/sha3
+
+/sha224.c
+/sha224.h
+/sha384.h
+/sha384.c
+/sha512-224.c
+/sha512-224.h
+/sha512-256.c
+/sha512-256.h
+
+/safersk.c
+/safersk.h
+
+/whirlpool256.c
+/whirlpool256.h
+
+/sha3-224.c
+/sha3-224.h
+/sha3-256.c
+/sha3-256.h
+/sha3-384.c
+/sha3-384.h
+/sha3-512.c
+/sha3-512.h
+/kmac128.h
+/kmac256.h
+/shake128.h
+/shake256.h
+/shake128-xof.h
+/shake256-xof.h
+
+/chacha20.h
+/chacha12.h
+/chacha8.h
+/chacha12-ietf.h
+/chacha20-ietf.h
+/chacha8-ietf.h
+/xchacha.h
+/xchacha20.h
+/xchacha12.h
+/xchacha8.h
+/chacha20-naclbox.h
+/chacha12-naclbox.h
+/chacha8-naclbox.h
+/chacha20-poly1305.h
+/chacha12-poly1305.h
+/chacha8-poly1305.h
+
+/salsa2012.h
+/salsa208.h
+/salsa20-ietf.h
+/salsa2012-ietf.h
+/salsa208-ietf.h
+/xsalsa20.h
+/xsalsa2012.h
+/xsalsa208.h
+/salsa20-naclbox.h
+/salsa2012-naclbox.h
+/salsa208-naclbox.h
+/salsa20-poly1305.h
+/salsa2012-poly1305.h
+/salsa208-poly1305.h
TEST_LIBS = libsymm.la
+noinst_LTLIBRARIES += libsymmtest.la
+libsymmtest_la_SOURCES =
+libsymmtest_la_CFLAGS = $(AM_CFLAGS) -DSRCDIR=\"$(srcdir)\"
+TEST_LIBS += libsymmtest.la
+
VPATH += $(srcdir)/modes
###--------------------------------------------------------------------------
blkc="$(BLKCS)" \
blkcmode="$(BLKCMODES)" \
blkcciphermode="$(BLKCCIPHERMODES)" \
+ blkcaeadmode="$(BLKCAEADMODES)" \
+ blkcmacmode="$(BLKCMACMODES)" \
hash="$(HASHES)" \
hashmode="$(HASHMODES)" \
hashciphermode="$(HASHCIPHERMODES)" \
## Initialize lists of known classes.
ALL_CIPHERS = $(CIPHER_MODES)
+ALL_AEADS = $(AEAD_MODES)
ALL_HASHES = $(HASHES)
ALL_MACS = $(MAC_MODES)
BLKCCIPHERMODES =
BLKCMODES += $(BLKCCIPHERMODES)
+BLKCAEADMODES =
+BLKCMODES += $(BLKCAEADMODES)
+
+BLKCMACMODES =
+BLKCMODES += $(BLKCMACMODES)
+
## A tool for translating the AES-contest test vectors into a form our test
## rigs understand.
EXTRA_DIST += aes-trans
BLKCS += cast128 cast256
libsymm_la_SOURCES += cast-s.c cast-sk.c cast-base.h
cast256.log: t/cast256
-EXTRA_DIST += t/cast256.aes
+EXTRA_DIST += t/cast256.aes t/cast256.local
MAINTAINERCLEANFILES += $(srcdir)/t/cast256
-t/cast256: t/cast256.aes
- $(AM_V_GEN)$(srcdir)/aes-trans CAST256 \
- <$(srcdir)/t/cast256.aes \
- >$(srcdir)/t/cast256.new && \
- mv $(srcdir)/t/cast256.new $(srcdir)/t/cast256
+t/cast256: t/cast256.aes t/cast256.local
+ $(AM_V_GEN)cd $(srcdir) && \
+ { ./aes-trans CAST256 <t/cast256.aes && \
+ cat t/cast256.local; \
+ } >t/cast256.new && \
+ mv t/cast256.new t/cast256
## IBM's `DES' block cipher, by Feistel, Coppersmith, and others.
BLKCS += des des3
mv $(precomp)/symm/mars-tab.c.new $(precomp)/symm/mars-tab.c
endif
mars.log: t/mars
-EXTRA_DIST += t/mars.aes
+EXTRA_DIST += t/mars.aes t/mars.local
MAINTAINERCLEANFILES += $(srcdir)/t/mars
-t/mars: t/mars.aes
- $(AM_V_GEN)$(srcdir)/aes-trans Mars \
- <$(srcdir)/t/mars.aes \
- >$(srcdir)/t/mars.new && \
- mv $(srcdir)/t/mars.new $(srcdir)/t/mars
+t/mars: t/mars.aes t/mars.local
+ $(AM_V_GEN)cd $(srcdir) && \
+ { ./aes-trans Mars <t/mars.aes && \
+ cat t/mars.local; \
+ } >t/mars.new && \
+ mv t/mars.new t/mars
## Daemen, Peeters, Van Assche and Rijmen's `Noekeon'.
BLKCS += noekeon
$(precomp)/symm/rijndael-tab.c
endif
rijndael.log: t/rijndael
-EXTRA_DIST += t/rijndael.aes
+EXTRA_DIST += t/rijndael.aes t/rijndael.local
MAINTAINERCLEANFILES += $(srcdir)/t/rijndael
-t/rijndael: t/rijndael.aes
- $(AM_V_GEN)$(srcdir)/aes-trans Rijndael \
- <$(srcdir)/t/rijndael.aes \
- >$(srcdir)/t/rijndael.new && \
- mv $(srcdir)/t/rijndael.new $(srcdir)/t/rijndael
+t/rijndael: t/rijndael.aes t/rijndael.local
+ $(AM_V_GEN)cd $(srcdir) && \
+ { ./aes-trans Rijndael <t/rijndael.aes && \
+ cat t/rijndael.local; \
+ } >t/rijndael.new && \
+ mv t/rijndael.new t/rijndael
## Massey's `SAFER' block ciphers.
BLKCS += safer safersk
check_PROGRAMS += serpent-check
TESTS += serpent-check
serpent.log: t/serpent
-EXTRA_DIST += t/serpent.aes
+EXTRA_DIST += t/serpent.aes t/serpent.local
MAINTAINERCLEANFILES += $(srcdir)/t/serpent
-t/serpent: t/serpent.aes
- $(AM_V_GEN)$(srcdir)/aes-trans Serpent -v rev=1 \
- <$(srcdir)/t/serpent.aes \
- >$(srcdir)/t/serpent.new && \
- mv $(srcdir)/t/serpent.new $(srcdir)/t/serpent
+t/serpent: t/serpent.aes t/serpent.local
+ $(AM_V_GEN)cd $(srcdir) && \
+ { ./aes-trans Serpent -v rev=1 <t/serpent.aes && \
+ cat t/serpent.local; \
+ } >t/serpent.new && \
+ mv t/serpent.new t/serpent
## The National Security Agency's `Skipjack' block cipher. You don't want to
## use this.
$(precomp)/symm/twofish-tab.c
endif
twofish.log: t/twofish
-EXTRA_DIST += t/twofish.aes
+EXTRA_DIST += t/twofish.aes t/twofish.local
MAINTAINERCLEANFILES += $(srcdir)/t/twofish
-t/twofish: t/twofish.aes
- $(AM_V_GEN)$(srcdir)/aes-trans Twofish \
- <$(srcdir)/t/twofish.aes \
- >$(srcdir)/t/twofish.new && \
- mv $(srcdir)/t/twofish.new $(srcdir)/t/twofish
+t/twofish: t/twofish.aes t/twofish.local
+ $(AM_V_GEN)cd $(srcdir) && \
+ { ./aes-trans Twofish <t/twofish.aes && \
+ cat t/twofish.local; \
+ } >t/twofish.new && \
+ mv t/twofish.new t/twofish
## The old NIST modes for DES.
BLKCCIPHERMODES += cbc cfb ecb ofb
## Counter mode.
BLKCCIPHERMODES += counter
+## CMAC mode.
+BLKCMACMODES += cmac pmac1
+
+## Various AEAD modes.
+pkginclude_HEADERS += ocb.h
+BLKCAEADMODES += ccm eax gcm ocb1 ocb3
+libsymm_la_SOURCES += ccm.c gcm.c ocb.c
+if CPUFAM_X86
+libsymm_la_SOURCES += gcm-x86ish-pclmul.S
+endif
+if CPUFAM_AMD64
+libsymm_la_SOURCES += gcm-x86ish-pclmul.S
+endif
+if CPUFAM_ARMEL
+libsymm_la_SOURCES += gcm-arm-crypto.S
+endif
+if CPUFAM_ARM64
+libsymm_la_SOURCES += gcm-arm64-pmull.S
+endif
+
+TESTS += gcm.t$(EXEEXT)
+EXTRA_DIST += t/gcm
+
###--------------------------------------------------------------------------
### Hash functions.
poly1305_p11_t_LDADD = $(TEST_LIBS) $(top_builddir)/libcatacomb.la
poly1305_p11_t_LDADD += $(mLib_LIBS) $(CATACOMB_LIBS) $(LIBS)
+## Combining Salsa20/ChaCha with Poly1305.
+pkginclude_HEADERS += latinpoly.h latinpoly-def.h
+libsymm_la_SOURCES += latinpoly.c chacha-poly1305.c salsa20-poly1305.c
+libsymmtest_la_SOURCES += latinpoly-test.c latinpoly-test.h
+
+ALL_AEADS += chacha20-poly1305 salsa20-poly1305
+ALL_AEADS += chacha12-poly1305 salsa2012-poly1305
+ALL_AEADS += chacha8-poly1305 salsa208-poly1305
+ALL_AEADS += chacha20-naclbox salsa20-naclbox
+ALL_AEADS += chacha12-naclbox salsa2012-naclbox
+ALL_AEADS += chacha8-naclbox salsa208-naclbox
+STUBS_HDR += ChaCha20-Poly1305,chacha20-poly1305,latinpoly
+STUBS_HDR += ChaCha12-Poly1305,chacha12-poly1305,latinpoly
+STUBS_HDR += ChaCha8-Poly1305,chacha8-poly1305,latinpoly
+STUBS_HDR += Salsa20-Poly1305,salsa20-poly1305,latinpoly
+STUBS_HDR += Salsa20/12-Poly1305,salsa2012-poly1305,latinpoly
+STUBS_HDR += Salsa20/8-Poly1305,salsa208-poly1305,latinpoly
+STUBS_HDR += ChaCha20-NaClBox,chacha20-naclbox,latinpoly
+STUBS_HDR += ChaCha12-NaClBox,chacha12-naclbox,latinpoly
+STUBS_HDR += ChaCha8-NaClBox,chacha8-naclbox,latinpoly
+STUBS_HDR += Salsa20-NaClBox,salsa20-naclbox,latinpoly
+STUBS_HDR += Salsa20/12-NaClBox,salsa2012-naclbox,latinpoly
+STUBS_HDR += Salsa20/8-NaClBox,salsa208-naclbox,latinpoly
+TESTS += chacha-poly1305.t$(EXEEXT)
+TESTS += salsa20-poly1305.t$(EXEEXT)
+
###--------------------------------------------------------------------------
### Autogenerated mode implementations.
pkginclude_HEADERS += $(GENMODES_H)
$(GENMODES_H): modes/gen-stamp
+## Additional test machinery.
+libsymmtest_la_SOURCES += modes-test.c modes-test.h
+
###--------------------------------------------------------------------------
### Autogenerated stub headers.
$(AM_V_GEN)$(multigen) -g $(srcdir)/gthingtab.c.in gciphertab.c \
what=gcipher cls=gccipher thing="$(ALL_CIPHERS)"
+## Table of AEAD classes.
+pkginclude_HEADERS += gaead.h
+CLEANFILES += gaeadtab.c
+libsymm_la_SOURCES += gaead.c
+nodist_libsymm_la_SOURCES += gaeadtab.c
+gaeadtab.c: gthingtab.c.in Makefile.am
+ $(AM_V_GEN)$(multigen) -g $(srcdir)/gthingtab.c.in gaeadtab.c \
+ what=gaead cls=gcaead thing="$(ALL_AEADS)"
+
## Table of hash classes.
pkginclude_HEADERS += ghash.h ghash-def.h
CLEANFILES += ghashtab.c
## Run the test programs.
TESTS += $(SYMM_TESTS)
EXTRA_DIST += $(SYMM_TEST_FILES)
+EXTRA_DIST += $(REGRESSION_TEST_FILES)
-## A piece of sample text for round-trip testing encryption modes.
-EXTRA_DIST += daftstory.h
+t/modes/%.regress:
+ $(MAKE) modes/$*.t && \
+ mkdir -p $(srcdir)/t/modes/ && \
+ modes/$*.t -o$(srcdir)/$@.new && \
+ mv $(srcdir)/$@.new $(srcdir)/$@
## Clean the debris from the `modes' subdirectory.
CLEANFILES += modes/*.to modes/*.t$(EXEEXT)
#define BLKC_STORE_E(PRE) BLKC_GLUE(STORE32_, BLKC_ENDIAN(PRE))
#define BLKC_LOAD_E(PRE) BLKC_GLUE(LOAD32_, BLKC_ENDIAN(PRE))
+#define BLKC_ID(x) (x)
+
/* --- Interface macros --- */
#define BLKC_STORE(PRE, b, w) \
BLKC_GLUE(BLKC_XMOVE_, BLKC_TYPE(PRE)) \
(PRE, w, wx, BLKC_BITS(PRE))
-#define BLKC_STEP(PRE, w) \
- BLKC_GLUE(BLKC_STEP_X_, BLKC_ENDIAN(PRE)) \
- (PRE, w)
+#define BLKC_BSTEP(PRE, w) BLKC_BADD(PRE, w, 1)
+#define BLKC_LSTEP(PRE, w) BLKC_LADD(PRE, w, 1)
+#define BLKC_STEP(PRE, w) BLKC_ADD(PRE, w, 1)
+
+#define BLKC_BADD(PRE, w, n) \
+ BLKC_GLUE(BLKC_BADD_X_, BLKC_ENDIAN(PRE)) \
+ (PRE, w, n)
+#define BLKC_LADD(PRE, w, n) \
+ BLKC_GLUE(BLKC_LADD_X_, BLKC_ENDIAN(PRE)) \
+ (PRE, w, n)
+#define BLKC_ADD(PRE, w, n) \
+ BLKC_GLUE(BLKC_ADD_X_, BLKC_ENDIAN(PRE)) \
+ (PRE, BLKC_ID, w, n)
#define BLKC_ZERO(PRE, w) \
BLKC_GLUE(BLKC_ZERO_, BLKC_TYPE(PRE)) \
(PRE, w, BLKC_BITS(PRE))
+#define BLKC_BSET(PRE, w, x) \
+ BLKC_GLUE(BLKC_BSET_X_, BLKC_ENDIAN(PRE)) \
+ (PRE, w, x)
+#define BLKC_LSET(PRE, w, x) \
+ BLKC_GLUE(BLKC_LSET_X_, BLKC_ENDIAN(PRE)) \
+ (PRE, w, x)
#define BLKC_SET(PRE, w, x) \
BLKC_GLUE(BLKC_SET_X_, BLKC_ENDIAN(PRE)) \
- (PRE, w, x)
+ (PRE, BLKC_ID, w, x)
+
+#define BLKC_BWORD(PRE, x) BLKC_GLUE(BLKC_BWORD_, BLKC_ENDIAN(PRE))(x)
+#define BLKC_LWORD(PRE, x) BLKC_GLUE(BLKC_LWORD_, BLKC_ENDIAN(PRE))(x)
#define BLKC_SHOW(PRE, tag, w) do { \
fputs(tag ": ", stdout); \
- BLKC_SKEL_X(PRE, BLKC_W(w);, printf("%08x ", *_w++);); \
+ BLKC_SKEL_X(PRE, const BLKC_W(w);, \
+ { printf("%08x ", BLKC_BWORD(PRE, *_w)); _w++; }); \
fputc('\n', stdout); \
} while (0)
+/* --- Utilities --- *
+ *
+ * These seem too hard to properly generalize, or I'd have put them in
+ * <mLib/bits.h>.
+ */
+
+#ifdef HAVE_UINT64
+# define BLKC_ADDC32(op, z_out, c_out, x, y) do { \
+ uint64 _t = (uint64)op(x) + (y); \
+ (z_out) = U32(op(_t)); (c_out) = _t >> 32; \
+ } while (0)
+#else
+# define BLKC_ADDC32(op, z_out, c_out, x, y) do { \
+ uint32 _x = op(x), _c = 0, _t; \
+ _t = U32(_x + (y)); (z_out) = op(_t); (c_out) = (_t < _x); \
+ } while (0)
+#endif
+
/* --- General implementation skeleton --- */
#define BLKC_SKEL(PRE, decl, guts) do { \
guts \
} while (0)
-#define BLKC_P(p) register octet *_p = (octet *)(p)
-#define BLKC_W(w) register uint32 *_w = (w)
-#define BLKC_WX(wx) register uint32 *_wx = (wx)
+#define BLKC_P(p) octet *_p = (octet *)(p)
+#define BLKC_W(w) uint32 *_w = (w)
+#define BLKC_WX(wx) uint32 *_wx = (wx)
/* --- Implementation for unusual block sizes --- */
#define BLKC_SKEL_X(PRE, decl, guts) \
BLKC_SKEL(PRE, unsigned _i; decl, \
- for (_i = 0; _i < PRE##_BLKSZ / 4; _i++) { \
+ for (_i = 0; _i < PRE##_BLKSZ/4; _i++) { \
guts \
})
#define BLKC_ZERO_X(PRE, w, n) \
BLKC_SKEL_X(PRE, BLKC_W(w);, *_w++ = 0;)
-#define BLKC_STEP_X_B(PRE, w) do { \
- unsigned _i = PRE##_BLKSZ / 4; BLKC_W(w); uint32 _x = 0; \
- while (_i && !_x) { _i--; _w[_i] = _x = U32(_w[_i] + 1); } \
+#define BLKC_BADD_X_B(PRE, w, n) BLKC_ADD_X_B(PRE, BLKC_ID, w, n)
+#define BLKC_BADD_X_L(PRE, w, n) BLKC_ADD_X_B(PRE, ENDSWAP32, w, n)
+#define BLKC_LADD_X_B(PRE, w, n) BLKC_ADD_X_L(PRE, ENDSWAP32, w, n)
+#define BLKC_LADD_X_L(PRE, w, n) BLKC_ADD_X_L(PRE, BLKC_ID, w, n)
+
+#define BLKC_ADD_X_B(PRE, op, w, n) do { \
+ unsigned _i = PRE##_BLKSZ/4; BLKC_W(w); uint32 _n = (n); \
+ while (_i-- && _n) BLKC_ADDC32(op, _w[_i], _n, _w[_i], _n); \
} while (0)
-#define BLKC_STEP_X_L(PRE, w) do { \
- unsigned _i = 0; BLKC_W(w); uint32 _x = 0; \
- while (_i < PRE##_BLKSZ / 4 && !_x) \
- { _w[_i] = _x = U32(_w[_i] + 1); _i++; } \
+#define BLKC_ADD_X_L(PRE, op, w, n) do { \
+ unsigned _i = 0; BLKC_W(w); uint32 _n = (n); \
+ while (_i < PRE##_BLKSZ/4 && _n) \
+ { BLKC_ADDC32(op, _w[_i], _n, _w[_i], _n); _i++; } \
} while (0)
-#define BLKC_SET_X_B(PRE, w, x) do { \
- unsigned _i; BLKC_W(w); unsigned long _x = x; \
- for (_i = 0; _i < PRE##_BLKSZ / 4; _i++) { \
- *_w++ = U32(_x); \
+#define BLKC_BSET_X_B(PRE, w, x) BLKC_SET_X_B(PRE, BLKC_ID, w, x)
+#define BLKC_BSET_X_L(PRE, w, x) BLKC_SET_X_B(PRE, ENDSWAP32, w, x)
+#define BLKC_LSET_X_B(PRE, w, x) BLKC_SET_X_L(PRE, ENDSWAP32, w, x)
+#define BLKC_LSET_X_L(PRE, w, x) BLKC_SET_X_L(PRE, BLKC_ID, w, x)
+
+#define BLKC_SET_X_B(PRE, op, w, x) do { \
+ unsigned _i; BLKC_W(w); unsigned long _x = x; _w += PRE##_BLKSZ/4; \
+ for (_i = 0; _i < PRE##_BLKSZ/4; _i++) { \
+ *--_w = U32(op(_x)); \
_x = ((_x & ~(unsigned long)MASK32) >> 16) >> 16; \
} \
} while (0)
-#define BLKC_SET_X_L(PRE, w, x) do { \
- unsigned _i; BLKC_W(w); unsigned long _x = x; _w += PRE##_BLKSZ / 4; \
- for (_i = 0; _i < PRE##_BLKSZ / 4; _i++) { \
- *--_w = U32(_x); \
+#define BLKC_SET_X_L(PRE, op, w, x) do { \
+ unsigned _i; BLKC_W(w); unsigned long _x = x; \
+ for (_i = 0; _i < PRE##_BLKSZ/4; _i++) { \
+ *_w++ = U32(op(_x)); \
_x = ((_x & ~(unsigned long)MASK32) >> 16) >> 16; \
} \
} while (0)
+#define BLKC_BWORD_B(x) (x)
+#define BLKC_BWORD_L(x) ENDSWAP32(x)
+#define BLKC_LWORD_B(x) ENDSWAP32(x)
+#define BLKC_LWORD_L(x) (x)
+
/* --- Implementation for known block sizes --- */
#define BLKC_SKEL_64(PRE, decl, op, guts) \
BLKC_GLUE(BLKC_SKEL_, n) \
(PRE, BLKC_W(w); const BLKC_WX(wx);, op, BLKC_XMOVE_GUTS)
+/*----- Binary field arithmetic -------------------------------------------*/
+
+#define BLKC_POLY_IRRED64 0x001b
+#define BLKC_POLY_IRRED96 0x0641
+#define BLKC_POLY_IRRED128 0x0087
+#define BLKC_POLY_IRRED192 0x0087
+#define BLKC_POLY_IRRED256 0x0425
+
+#define BLKC_POLY_PRIM64 0x001b
+#define BLKC_POLY_PRIM96 0x0641
+#define BLKC_POLY_PRIM128 0x0087
+#define BLKC_POLY_PRIM192 0x8821
+#define BLKC_POLY_PRIM256 0x0425
+
+#define BLKC_POLY(PRE, f) BLKC_GLUE(BLKC_POLY_##f, BLKC_BITS(PRE))
+
+#define BLKC_BLSHIFT(PRE, f, z, x) \
+ BLKC_GLUE(BLKC_BLSHIFT_X_, BLKC_ENDIAN(PRE)) \
+ (PRE, f, z, x)
+#define BLKC_LLSHIFT(PRE, f, z, x) \
+ BLKC_GLUE(BLKC_LLSHIFT_X_, BLKC_ENDIAN(PRE)) \
+ (PRE, f, z, x)
+#define BLKC_LSHIFT(PRE, f, z, x) \
+ BLKC_GLUE(BLKC_LSHIFT_X_, BLKC_ENDIAN(PRE)) \
+ (PRE, BLKC_ID, f, z, x)
+
+#define BLKC_BRSHIFT(PRE, f, z, x) \
+ BLKC_GLUE(BLKC_BRSHIFT_X_, BLKC_ENDIAN(PRE)) \
+ (PRE, f, z, x)
+#define BLKC_LRSHIFT(PRE, f, z, x) \
+ BLKC_GLUE(BLKC_LRSHIFT_X_, BLKC_ENDIAN(PRE)) \
+ (PRE, f, z, x)
+#define BLKC_RSHIFT(PRE, f, z, x) \
+ BLKC_GLUE(BLKC_RSHIFT_X_, BLKC_ENDIAN(PRE)) \
+ (PRE, BLKC_ID, f, z, x)
+
+#define BLKC_BLSHIFT_X_B(PRE, f, z, x) BLKC_LSHIFT_X_B(PRE, BLKC_ID, f, z, x)
+#define BLKC_LLSHIFT_X_B(PRE, f, z, x) BLKC_LSHIFT_X_L(PRE, ENDSWAP32, f, z, x)
+#define BLKC_BLSHIFT_X_L(PRE, f, z, x) BLKC_LSHIFT_X_B(PRE, ENDSWAP32, f, z, x)
+#define BLKC_LLSHIFT_X_L(PRE, f, z, x) BLKC_LSHIFT_X_L(PRE, BLKC_ID, f, z, x)
+
+#define BLKC_BRSHIFT_X_B(PRE, f, z, x) BLKC_RSHIFT_X_B(PRE, BLKC_ID, f, z, x)
+#define BLKC_LRSHIFT_X_B(PRE, f, z, x) BLKC_RSHIFT_X_L(PRE, ENDSWAP32, f, z, x)
+#define BLKC_BRSHIFT_X_L(PRE, f, z, x) BLKC_RSHIFT_X_B(PRE, ENDSWAP32, f, z, x)
+#define BLKC_LRSHIFT_X_L(PRE, f, z, x) BLKC_RSHIFT_X_L(PRE, BLKC_ID, f, z, x)
+
+#define BLKC_LSHIFT_X_B(PRE, op, f, z, x) do { \
+ uint32 *_z = (z); const uint32 *_x = (x); \
+ uint32 _t = op(_x[0]), _m = -(uint32)((_t >> 31)&1u), \
+ _c = BLKC_POLY(PRE, f)&_m; \
+ unsigned _i; \
+ \
+ for (_i = PRE##_BLKSZ/4; _i-- > 0; ) \
+ { _t = op(_x[_i]); _z[_i] = op((_t << 1) ^ _c); _c = (_t >> 31)&1u; } \
+} while (0)
+
+#define BLKC_RSHIFT_X_B(PRE, op, f, z, x) do { \
+ uint32 *_z = (z); const uint32 *_x = (x); \
+ uint32 _t, _t0 = op(_x[PRE##_BLKSZ/4 - 1]), _m = -(uint32)(_t0&1u), \
+ _c = 0x80000000&_m; \
+ unsigned _i; \
+ \
+ for (_i = 0; _i < PRE##_BLKSZ/4 - 1; _i++) \
+ { _t = op(_x[_i]); _z[_i] = op((_t >> 1) ^ _c); _c = (_t&1u) << 31; } \
+ _t0 ^= BLKC_POLY(PRE, f)&_m; _z[PRE##_BLKSZ/4 - 1] = op((_t0 >> 1) ^ _c); \
+} while (0)
+
+#define BLKC_LSHIFT_X_L(PRE, op, f, z, x) do { \
+ uint32 *_z = (z); const uint32 *_x = (x); \
+ uint32 _t = op(_x[PRE##_BLKSZ/4 - 1]), _m = -(uint32)((_t >> 31)&1u), \
+ _c = BLKC_POLY(PRE, f)&_m; \
+ unsigned _i; \
+ \
+ for (_i = 0; _i < PRE##_BLKSZ/4; _i++) \
+ { _t = op(_x[_i]); _z[_i] = op((_t << 1) ^ _c); _c = (_t >> 31)&1u; } \
+} while (0)
+
+#define BLKC_RSHIFT_X_L(PRE, op, f, z, x) do { \
+ uint32 *_z = (z); const uint32 *_x = (x); \
+ uint32 _t, _t0 = op(_x[0]), _m = -(uint32)(_t0&1u), \
+ _c = 0x80000000&_m; \
+ unsigned _i; \
+ \
+ for (_i = PRE##_BLKSZ/4 - 1; _i-- > 1; ) \
+ { _t = op(_x[_i]); _z[_i] = op((_t >> 1) ^ _c); _c = (_t&1u) << 31; } \
+ _t0 ^= BLKC_POLY(PRE, f)&_m; _z[0] = op((_t0 >> 1) ^ _c); \
+} while (0)
+
/*----- Test rig for block ciphers ----------------------------------------*/
/* --- @BLKC_TEST@ --- *
static int pre##_verify(dstr *v) \
{ \
pre##_ctx k; \
- uint32 p[PRE##_BLKSZ / 4]; \
- uint32 c[PRE##_BLKSZ / 4]; \
- uint32 d[PRE##_BLKSZ / 4]; \
+ uint32 p[PRE##_BLKSZ/4]; \
+ uint32 c[PRE##_BLKSZ/4]; \
+ uint32 d[PRE##_BLKSZ/4]; \
dstr b = DSTR_INIT; \
int ok = 1; \
\
*/ \
\
void pre##_cbcgetiv(const pre##_cbcctx *ctx, void *iv) \
-{ \
- BLKC_STORE(PRE, iv, ctx->iv); \
-} \
+ { BLKC_STORE(PRE, iv, ctx->a); } \
\
/* --- @pre_cbcsetiv@ --- * \
* \
*/ \
\
void pre##_cbcsetiv(pre##_cbcctx *ctx, const void *iv) \
-{ \
- BLKC_LOAD(PRE, ctx->iv, iv); \
-} \
+ { BLKC_LOAD(PRE, ctx->a, iv); } \
\
/* --- @pre_cbcsetkey@ --- * \
* \
*/ \
\
void pre##_cbcsetkey(pre##_cbcctx *ctx, const pre##_ctx *k) \
-{ \
- ctx->ctx = *k; \
-} \
+ { ctx->ctx = *k; } \
\
/* --- @pre_cbcinit@ --- * \
* \
*/ \
\
void pre##_cbcinit(pre##_cbcctx *ctx, \
- const void *key, size_t sz, \
- const void *iv) \
+ const void *key, size_t sz, \
+ const void *iv) \
{ \
static const octet zero[PRE##_BLKSZ] = { 0 }; \
+ \
pre##_init(&ctx->ctx, key, sz); \
- BLKC_LOAD(PRE, ctx->iv, iv ? iv : zero); \
+ BLKC_LOAD(PRE, ctx->a, iv ? iv : zero); \
} \
\
/* --- @pre_cbcencrypt@ --- * \
*/ \
\
void pre##_cbcencrypt(pre##_cbcctx *ctx, \
- const void *src, void *dest, \
- size_t sz) \
+ const void *src, void *dest, \
+ size_t sz) \
{ \
const octet *s = src; \
octet *d = dest; \
+ octet b[PRE##_BLKSZ], bb[PRE##_BLKSZ]; \
+ octet y; \
+ unsigned i; \
\
/* --- Empty blocks are trivial --- */ \
\
- if (!sz) \
- return; \
+ if (!sz) return; \
\
/* --- Extra magical case for a short block --- * \
* \
*/ \
\
if (sz < PRE##_BLKSZ) { \
- octet b[PRE##_BLKSZ]; \
- unsigned i; \
- \
- pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv); \
- BLKC_STORE(PRE, b, ctx->iv); \
- if (d) { \
- for (i = 0; i < sz; i++) \
- d[i] = b[i] ^ (s ? s[i] : 0); \
- } \
+ pre##_eblk(&ctx->ctx, ctx->a, ctx->a); \
+ BLKC_STORE(PRE, b, ctx->a); \
+ if (!d) d = bb; \
+ for (i = 0; i < sz; i++) d[i] = b[i] ^ (s ? s[i] : 0); \
memmove(b, b + sz, PRE##_BLKSZ - sz); \
memcpy(b + PRE##_BLKSZ - sz, d, sz); \
- BLKC_LOAD(PRE, ctx->iv, b); \
+ BLKC_LOAD(PRE, ctx->a, b); \
return; \
} \
\
* and keep a copy of the ciphertext for the next block. \
*/ \
\
- while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) { \
- if (s) { \
- BLKC_XLOAD(PRE, ctx->iv, s); \
- s += PRE##_BLKSZ; \
- } \
- pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv); \
- if (d) { \
- BLKC_STORE(PRE, d, ctx->iv); \
- d += PRE##_BLKSZ; \
- } \
+ while (sz >= 2*PRE##_BLKSZ || sz == PRE##_BLKSZ) { \
+ if (s) { BLKC_XLOAD(PRE, ctx->a, s); s += PRE##_BLKSZ; } \
+ pre##_eblk(&ctx->ctx, ctx->a, ctx->a); \
+ if (d) { BLKC_STORE(PRE, d, ctx->a); d += PRE##_BLKSZ; } \
sz -= PRE##_BLKSZ; \
} \
\
*/ \
\
if (sz) { \
- octet b[PRE##_BLKSZ]; \
- unsigned i; \
\
/* --- Let @sz@ be the size of the partial block --- */ \
\
* block. \
*/ \
\
- if (s) BLKC_XLOAD(PRE, ctx->iv, s); \
- pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv); \
- BLKC_STORE(PRE, b, ctx->iv); \
+ if (s) BLKC_XLOAD(PRE, ctx->a, s); \
+ pre##_eblk(&ctx->ctx, ctx->a, ctx->a); \
+ BLKC_STORE(PRE, b, ctx->a); \
\
/* --- Second stage --- * \
* \
if (s) s += PRE##_BLKSZ; \
if (d) d += PRE##_BLKSZ; \
for (i = 0; i < sz; i++) { \
- register octet x = b[i]; \
+ y = b[i]; \
if (s) b[i] ^= s[i]; \
- if (d) d[i] = x; \
+ if (d) d[i] = y; \
} \
- BLKC_LOAD(PRE, ctx->iv, b); \
- pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv); \
- if (d) BLKC_STORE(PRE, d - PRE##_BLKSZ, ctx->iv); \
+ BLKC_LOAD(PRE, ctx->a, b); \
+ pre##_eblk(&ctx->ctx, ctx->a, ctx->a); \
+ if (d) BLKC_STORE(PRE, d - PRE##_BLKSZ, ctx->a); \
} \
\
/* --- Done --- */ \
*/ \
\
void pre##_cbcdecrypt(pre##_cbcctx *ctx, \
- const void *src, void *dest, \
- size_t sz) \
+ const void *src, void *dest, \
+ size_t sz) \
{ \
const octet *s = src; \
octet *d = dest; \
+ uint32 t[PRE##_BLKSZ/4], u[PRE##_BLKSZ/4]; \
+ octet b[PRE##_BLKSZ], c[PRE##_BLKSZ]; \
+ octet y; \
+ unsigned i; \
\
/* --- Empty blocks are trivial --- */ \
\
- if (!sz) \
- return; \
+ if (!sz) return; \
\
/* --- Extra magical case for a short block --- * \
* \
*/ \
\
if (sz < PRE##_BLKSZ) { \
- octet b[PRE##_BLKSZ], c[PRE##_BLKSZ]; \
- unsigned i; \
- \
- pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv); \
- BLKC_STORE(PRE, b, ctx->iv); \
- for (i = 0; i < sz; i++) { \
- register octet x = s[i]; \
- d[i] = b[i] ^ x; \
- c[i] = x; \
- } \
+ pre##_eblk(&ctx->ctx, ctx->a, ctx->a); \
+ BLKC_STORE(PRE, b, ctx->a); \
+ for (i = 0; i < sz; i++) { y = s[i]; d[i] = b[i] ^ y; c[i] = y; } \
memmove(b, b + sz, PRE##_BLKSZ - sz); \
memcpy(b + PRE##_BLKSZ - sz, c, sz); \
- BLKC_LOAD(PRE, ctx->iv, b); \
+ BLKC_LOAD(PRE, ctx->a, b); \
return; \
} \
\
* and keep a copy of the ciphertext for the next block. \
*/ \
\
- while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) { \
- uint32 b[PRE##_BLKSZ / 4], niv[PRE##_BLKSZ / 4]; \
- BLKC_LOAD(PRE, niv, s); \
- pre##_dblk(&ctx->ctx, niv, b); \
- BLKC_XSTORE(PRE, d, b, ctx->iv); \
- BLKC_MOVE(PRE, ctx->iv, niv); \
- s += PRE##_BLKSZ; \
- d += PRE##_BLKSZ; \
+ while (sz >= 2*PRE##_BLKSZ || sz == PRE##_BLKSZ) { \
+ BLKC_LOAD(PRE, t, s); s += PRE##_BLKSZ; \
+ pre##_dblk(&ctx->ctx, t, u); \
+ BLKC_XSTORE(PRE, d, u, ctx->a); d += PRE##_BLKSZ; \
+ BLKC_MOVE(PRE, ctx->a, t); \
sz -= PRE##_BLKSZ; \
} \
\
*/ \
\
if (sz) { \
- octet b[PRE##_BLKSZ]; \
- uint32 bk[PRE##_BLKSZ / 4], niv[PRE##_BLKSZ / 4]; \
- unsigned i; \
\
/* --- Let @sz@ be the size of the partial block --- */ \
\
* is carried over for the next encryption operation. \
*/ \
\
- BLKC_LOAD(PRE, niv, s); \
- pre##_dblk(&ctx->ctx, niv, bk); \
+ BLKC_LOAD(PRE, t, s); \
+ pre##_dblk(&ctx->ctx, t, u); \
\
/* --- Second stage --- * \
* \
* three. \
*/ \
\
- BLKC_STORE(PRE, b, bk); \
+ BLKC_STORE(PRE, b, u); \
s += PRE##_BLKSZ; \
d += PRE##_BLKSZ; \
- for (i = 0; i < sz; i++) { \
- register octet x = s[i]; \
- d[i] = b[i] ^ x; \
- b[i] = x; \
- } \
+ for (i = 0; i < sz; i++) { y = s[i]; d[i] = b[i] ^ y; b[i] = y; } \
\
/* --- Third stage --- * \
* \
* recover the complete plaintext block. \
*/ \
\
- BLKC_LOAD(PRE, bk, b); \
- pre##_dblk(&ctx->ctx, bk, bk); \
- BLKC_XSTORE(PRE, d - PRE##_BLKSZ, bk, ctx->iv); \
- BLKC_MOVE(PRE, ctx->iv, niv); \
+ BLKC_LOAD(PRE, u, b); \
+ pre##_dblk(&ctx->ctx, u, u); \
+ BLKC_XSTORE(PRE, d - PRE##_BLKSZ, u, ctx->a); \
+ BLKC_MOVE(PRE, ctx->a, t); \
} \
\
/* --- Done --- */ \
} \
\
static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) \
-{ \
- gctx *g = (gctx *)c; \
- pre##_cbcencrypt(&g->k, s, t, sz); \
-} \
+ { gctx *g = (gctx *)c; pre##_cbcencrypt(&g->k, s, t, sz); } \
\
static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz) \
-{ \
- gctx *g = (gctx *)c; \
- pre##_cbcdecrypt(&g->k, s, t, sz); \
-} \
+ { gctx *g = (gctx *)c; pre##_cbcdecrypt(&g->k, s, t, sz); } \
\
static void gdestroy(gcipher *c) \
-{ \
- gctx *g = (gctx *)c; \
- BURN(*g); \
- S_DESTROY(g); \
-} \
+ { gctx *g = (gctx *)c; BURN(*g); S_DESTROY(g); } \
\
static void gsetiv(gcipher *c, const void *iv) \
-{ \
- gctx *g = (gctx *)c; \
- pre##_cbcsetiv(&g->k, iv); \
-} \
+ { gctx *g = (gctx *)c; pre##_cbcsetiv(&g->k, iv); } \
\
static const gcipher_ops gops = { \
&pre##_cbc, \
#ifdef TEST_RIG
-#include <stdio.h>
-
-#include "daftstory.h"
+#include "modes-test.h"
/* --- @CBC_TEST@ --- *
*
#define CBC_TESTX(PRE, pre, name, fname) \
\
-/* --- Initial plaintext for the test --- */ \
- \
-static const octet text[] = TEXT; \
+static pre##_ctx key; \
+static pre##_cbcctx ctx; \
\
-/* --- Key and IV to use --- */ \
+static void pre##_cbc_test_setup(const octet *k, size_t ksz) \
+ { pre##_init(&key, k, ksz); pre##_cbcsetkey(&ctx, &key); } \
\
-static const octet key[] = KEY; \
-static const octet iv[] = IV; \
+static void pre##_cbc_test_reset(const octet *iv) \
+ { pre##_cbcsetiv(&ctx, iv); } \
\
-/* --- Buffers for encryption and decryption output --- */ \
+static void pre##_cbc_test_enc(const octet *s, octet *d, size_t sz) \
+ { pre##_cbcencrypt(&ctx, s, d, sz); } \
\
-static octet ct[sizeof(text)]; \
-static octet pt[sizeof(text)]; \
+static void pre##_cbc_test_dec(const octet *s, octet *d, size_t sz) \
+ { pre##_cbcdecrypt(&ctx, s, d, sz); } \
\
-static void hexdump(const octet *p, size_t sz, size_t off) \
+int main(int argc, char *argv[]) \
{ \
- const octet *q = p + sz; \
- for (sz = 0; p < q; p++, sz++) { \
- printf("%02x", *p); \
- if ((off + sz + 1) % PRE##_BLKSZ == 0) \
- putchar(':'); \
- } \
-} \
- \
-int main(void) \
-{ \
- size_t sz = 0, rest; \
- pre##_cbcctx ctx; \
- pre##_ctx k; \
- int status = 0; \
- int done = 0; \
- \
- size_t keysz = PRE##_KEYSZ ? \
- PRE##_KEYSZ : strlen((const char *)key); \
- \
- fputs(name "-cbc: ", stdout); \
- \
- pre##_init(&k, key, keysz); \
- pre##_cbcsetkey(&ctx, &k); \
- \
- while (sz <= sizeof(text)) { \
- rest = sizeof(text) - sz; \
- memcpy(ct, text, sizeof(text)); \
- pre##_cbcsetiv(&ctx, iv); \
- pre##_cbcencrypt(&ctx, ct, ct, sz); \
- pre##_cbcencrypt(&ctx, ct + sz, ct + sz, rest); \
- memcpy(pt, ct, sizeof(text)); \
- pre##_cbcsetiv(&ctx, iv); \
- pre##_cbcdecrypt(&ctx, pt, pt, sz); \
- pre##_cbcdecrypt(&ctx, pt + sz, pt + sz, rest); \
- if (memcmp(pt, text, sizeof(text)) == 0) { \
- done++; \
- if (sizeof(text) < 40 || done % 8 == 0) \
- fputc('.', stdout); \
- if (done % 480 == 0) \
- fputs("\n\t", stdout); \
- fflush(stdout); \
- } else { \
- printf("\nError (sz = %lu)\n", (unsigned long)sz); \
- status = 1; \
- printf("\tplaintext = "); hexdump(text, sz, 0); \
- printf(", "); hexdump(text + sz, rest, sz); \
- fputc('\n', stdout); \
- printf("\tciphertext = "); hexdump(ct, sz, 0); \
- printf(", "); hexdump(ct + sz, rest, sz); \
- fputc('\n', stdout); \
- printf("\trecovered text = "); hexdump(pt, sz, 0); \
- printf(", "); hexdump(pt + sz, rest, sz); \
- fputc('\n', stdout); \
- fputc('\n', stdout); \
- } \
- if (sz < 63) \
- sz++; \
- else \
- sz += 9; \
- } \
- \
- fputs(status ? " failed\n" : " ok\n", stdout); \
- return (status); \
+ return test_encmode(fname "-cbc", PRE##_KEYSZ, PRE##_BLKSZ, \
+ 1, TEMF_REFALIGN, \
+ pre##_cbc_test_setup, pre##_cbc_test_reset, \
+ pre##_cbc_test_enc, pre##_cbc_test_dec, \
+ argc, argv); \
}
#else
\
typedef struct pre##_cbcctx { \
pre##_ctx ctx; /* Underlying cipher context */ \
- uint32 iv[PRE##_BLKSZ / 4]; /* Previous ciphertext or IV */ \
+ uint32 a[PRE##_BLKSZ/4]; /* Previous ciphertext or IV */ \
} pre##_cbcctx; \
\
/* --- @pre_cbcgetiv@ --- * \
--- /dev/null
+/* -*-c-*-
+ *
+ * The CCM authenticated-encryption mode
+ *
+ * (c) 2017 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef CATACOMB_CCM_DEF_H
+#define CATACOMB_CCM_DEF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#ifndef CATACOMB_ARENA_H
+# include "arena.h"
+#endif
+
+#ifndef CATACOMB_BLKC_H
+# include "blkc.h"
+#endif
+
+#ifndef CATACOMB_CT_H
+# include "ct.h"
+#endif
+
+#ifndef CATACOMB_KEYSZ_H
+# include "keysz.h"
+#endif
+
+#ifndef CATACOMB_PARANOIA_H
+# include "paranoia.h"
+#endif
+
+#ifndef CATACOMB_RSVR_H
+# include "rsvr.h"
+#endif
+
+/*----- Common machinery --------------------------------------------------*/
+
+/* --- @ccm_check@ --- *
+ *
+ * Arguments: @const ccm_params *p@ = pointer to parameters
+ *
+ * Returns: True (nonzero) if the parameters are OK; false (zero) if
+ * there's a problem.
+ *
+ * Use: Verify that the CCM parameters are acceptable.
+ */
+
+extern int ccm_check(const ccm_params */*p*/);
+
+/* --- @ccm_fmthdr@ --- *
+ *
+ * Arguments: @const ccm_params *p@ = pointer to parameters
+ * @octet *b@ = block-size buffer to write header
+ * @const void *n@ = pointer to nonce
+ *
+ * Returns: ---
+ *
+ * Use: Format a MAC header block.
+ */
+
+extern void ccm_fmthdr(const ccm_params */*p*/,
+ octet */*b*/, const void */*n*/);
+
+/* --- @ccm_fmtctr@ --- *
+ *
+ * Arguments: @const ccm_params *p@ = pointer to parameters
+ * @octet *b@ = block-size buffer to write header
+ * @const void *n@ = pointer to nonce
+ *
+ * Returns: ---
+ *
+ * Use: Format an initial counter block.
+ */
+
+extern void ccm_fmtctr(const ccm_params */*p*/,
+ octet */*b*/, const void */*n*/);
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @CCM_DEF@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Creates an implementation for the CCM authenticated-
+ * encryption mode.
+ */
+
+#define CCM_DEF(PRE, pre) CCM_DEFX(PRE, pre, #pre, #pre)
+
+#define CCM_DEFX(PRE, pre, name, fname) \
+ \
+const octet pre##_ccmnoncesz[] = \
+ { KSZ_RANGE, PRE##_BLKSZ/2 - (PRE##_BLKSZ <= 16 ? 1 : 2), \
+ CCM_NSZMIN(PRE), CCM_NSZMAX(PRE), 1 }; \
+const octet pre##_ccmtagsz[] = \
+ { KSZ_RANGE, CCM_TSZMAX(PRE), \
+ CCM_TSZMIN(PRE), CCM_TSZMAX(PRE), PRE##_BLKSZ == 16 ? 2 : 1 }; \
+ \
+static const rsvr_policy pre##_ccmpolicy = \
+ { RSVRF_FULL, PRE##_BLKSZ, PRE##_BLKSZ }; \
+ \
+/* --- @pre_ccminthash@ --- * \
+ * \
+ * Arguments: @pre_ccmctx *ctx@ = pointer to context block \
+ * @const void *p@ = pointer to material to hash \
+ * @size_t sz@ = size of the input buffer \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Internal operation for feeding stuff into the CBC-MAC \
+ * context. \
+ */ \
+ \
+static void pre##_ccminthash(pre##_ccmctx *ctx, \
+ const void *p, size_t sz) \
+{ \
+ rsvr_state st; \
+ const octet *q; \
+ \
+ rsvr_setup(&st, &pre##_ccmpolicy, ctx->b, &ctx->off, p, sz); \
+ RSVR_DO(&st) while ((q = RSVR_NEXT(&st, PRE##_BLKSZ)) != 0) { \
+ BLKC_XLOAD(PRE, ctx->a, q); \
+ pre##_eblk(&ctx->k, ctx->a, ctx->a); \
+ } \
+} \
+ \
+/* --- @pre_ccminit@ --- * \
+ * \
+ * Arguments: @pre_ccmctx *aad@ = pointer to CCM context \
+ * @const pre_ctx *k@ = pointer to key material \
+ * @const void *n@ = pointer to nonce \
+ * @size_t nsz@ = size of the nonce \
+ * @size_t hsz@ = size of the AAD \
+ * @size_t msz@ = size of the message/ciphertext \
+ * @size_t tsz@ = size of the tag to produce \
+ * \
+ * Returns: Zero on success; nonzero if the parameters are invalid. \
+ * \
+ * Use: Initialize an CCM operation context with a given key. \
+ * \
+ * The original key needn't be kept around any more. \
+ */ \
+ \
+int pre##_ccminit(pre##_ccmctx *ctx, const pre##_ctx *k, \
+ const void *n, size_t nsz, \
+ size_t hsz, size_t msz, size_t tsz) \
+ { ctx->k = *k; return (pre##_ccmreinit(ctx, n, nsz, hsz, msz, tsz)); } \
+ \
+/* --- @pre_ccmreinit@ --- * \
+ * \
+ * Arguments: @pre_ccmctx *ctx@ = pointer to CCM context \
+ * @const void *n@ = pointer to nonce \
+ * @size_t nsz@ = size of nonce \
+ * @size_t hsz@ = size of the AAD \
+ * @size_t msz@ = size of the message/ciphertext \
+ * @size_t tsz@ = size of the tag to produce \
+ * \
+ * Returns: Zero on success; nonzero if the parameters are invalid. \
+ * \
+ * Use: Reinitialize an CCM operation context, changing the \
+ * nonce. \
+ */ \
+ \
+int pre##_ccmreinit(pre##_ccmctx *ctx, const void *n, size_t nsz, \
+ size_t hsz, size_t msz, size_t tsz) \
+{ \
+ kludge64 t; \
+ octet b[12]; \
+ size_t sz; \
+ \
+ /* Set up the parameters and check that they make sense. */ \
+ ctx->p.hsz = hsz; ctx->p.msz = msz; \
+ ctx->p.bsz = PRE##_BLKSZ; ctx->p.nsz = nsz; ctx->p.tsz = tsz; \
+ if (!ccm_check(&ctx->p)) return (-1); \
+ \
+ /* Prepare the counter and the final MAC mask. The initial counter \
+ * is used to make the MAC mask, so generate that, keeping it for \
+ * later. \
+ */ \
+ ccm_fmtctr(&ctx->p, ctx->b, n); \
+ BLKC_LOAD(PRE, ctx->c, ctx->b); \
+ pre##_eblk(&ctx->k, ctx->c, ctx->s0); \
+ \
+ /* Prepare the MAC header and leave it in the buffer. */ \
+ ccm_fmthdr(&ctx->p, ctx->b, n); \
+ BLKC_ZERO(PRE, ctx->a); \
+ \
+ /* Initialize our state. The buffer is currently full (with the \
+ * MAC header), and we're always awaiting AAD, though we've not yet \
+ * seen any. (Even if we're not expecting AAD, this will trigger \
+ * appropriate initialization when encryption or decryption begins.) \
+ */ \
+ ctx->off = PRE##_BLKSZ; ctx->i = 0; \
+ ctx->st = CCMST_AAD; \
+ \
+ /* If there's AAD to come, then do the AAD framing. This aligns \
+ * badly with the blocking, so feed the framing in the hard way. \
+ */ \
+ if (hsz) { \
+ if (hsz < 0xfffe) \
+ { STORE16(b, hsz); sz = 2; } \
+ else if (hsz <= MASK32) \
+ { b[0] = 0xff; b[1] = 0xfe; STORE32(b + 2, hsz); sz = 6; } \
+ else { \
+ b[0] = b[1] = 0xff; \
+ ASSIGN64(t, hsz); STORE64_(b + 2, t); \
+ sz = 10; \
+ } \
+ pre##_ccminthash(ctx, b, sz); \
+ } \
+ \
+ /* All done. */ \
+ return (0); \
+} \
+ \
+/* --- @pre_ccmaadhash@ --- * \
+ * \
+ * Arguments: @pre_ccmctx *ctx@ = pointer to AAD context \
+ * @const void *p@ = pointer to AAD material \
+ * @size_t sz@ = length of AAD material \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Feeds AAD into the context. This must be done before \
+ * any of the message/ciphertext is processed because CCM \
+ * is really annoying like that. \
+ */ \
+ \
+void pre##_ccmaadhash(pre##_ccmctx *ctx, const void *p, size_t sz) \
+{ \
+ assert(ctx->st == CCMST_AAD); \
+ assert(sz <= ctx->p.hsz - ctx->i); \
+ ctx->i += sz; \
+ pre##_ccminthash(ctx, p, sz); \
+} \
+ \
+/* --- @pre_ccmencdecsetup@ --- * \
+ * \
+ * Arguments: @pre_ccmctx *ctx@ = pointer to context block \
+ * @size_t sz@ = size of message block \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Prepares for an encrypt or decryption operation, \
+ * transitioning from the AAD state and updating the \
+ * message size. \
+ */ \
+ \
+static void pre##_ccmencdecsetup(pre##_ccmctx *ctx, size_t sz) \
+{ \
+ if (ctx->st != CCMST_MSG) { \
+ /* Make sure we're currently in the AAD state and we've seen all of \
+ * the AAD we expected. \
+ */ \
+ assert(ctx->st == CCMST_AAD); \
+ assert(ctx->i == ctx->p.hsz); \
+ \
+ /* Pad the final AAD block out until we hit a block boundary. Note \
+ * that we don't cycle the block cipher here: instead, leave the \
+ * buffer full so that we do that next time. \
+ */ \
+ memset(ctx->b + ctx->off, 0, PRE##_BLKSZ - ctx->off); \
+ ctx->off = PRE##_BLKSZ; \
+ \
+ /* Now we're ready to process the message text. */ \
+ ctx->st = CCMST_MSG; ctx->i = 0; \
+ } \
+ \
+ /* Update the size. */ \
+ assert(sz <= ctx->p.msz - ctx->i); \
+ ctx->i += sz; \
+} \
+ \
+/* --- @pre_ccmencrypt@ --- * \
+ * \
+ * Arguments: @pre_ccmctx *ctx@ = pointer to CCM operation context \
+ * @const void *src@ = pointer to plaintext message chunk \
+ * @size_t sz@ = size of the plaintext \
+ * @buf *dst@ = a buffer to write the ciphertext to \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Encrypts a chunk of a plaintext message, writing a \
+ * chunk of ciphertext to the output buffer and updating \
+ * the operation state. \
+ * \
+ * For CCM, we always write a ciphertext chunk the same \
+ * size as the plaintext. The messing about with @buf@ \
+ * objects makes the interface consistent with other AEAD \
+ * schemes which can't do this. \
+ */ \
+ \
+int pre##_ccmencrypt(pre##_ccmctx *ctx, \
+ const void *src, size_t sz, buf *dst) \
+{ \
+ rsvr_plan plan; \
+ uint32 t[PRE##_BLKSZ/4], u[PRE##_BLKSZ]; \
+ const octet *p = src; \
+ octet *q, *r, y; \
+ \
+ /* Allocate space for the ciphertext. */ \
+ if (sz) { q = buf_get(dst, sz); if (!q) return (-1); } \
+ else q = 0; \
+ \
+ /* Set stuff up. */ \
+ pre##_ccmencdecsetup(ctx, sz); \
+ \
+ /* Determine the buffering plan. Our buffer is going to do double- \
+ * duty here. The end portion is going to contain mask from the \
+ * encrypted counter which we mix into the plaintext to encrypt it; \
+ * the start portion, which originally mask bytes we've already used, \
+ * will hold the input plaintext, which will eventually be \
+ * collected into the CBC-MAC state. \
+ */ \
+ rsvr_mkplan(&plan, &pre##_ccmpolicy, ctx->off, sz); \
+ \
+ /* Initial portion, fulfilled from the buffer. If the buffer is \
+ * empty, then that means that we haven't yet encrypted the current \
+ * counter, so we should do that and advance it. \
+ */ \
+ if (plan.head) { \
+ if (!ctx->off) { \
+ BLKC_BSTEP(PRE, ctx->c); pre##_eblk(&ctx->k, ctx->c, t); \
+ BLKC_STORE(PRE, ctx->b, t); \
+ } \
+ r = ctx->b + ctx->off; ctx->off += plan.head; \
+ while (plan.head--) { y = *p++; *q++ = y ^ *r; *r++ = y; } \
+ } \
+ \
+ /* If we've filled up the buffer then we need to cycle the MAC and \
+ * reset the offset. \
+ */ \
+ if (plan.from_rsvr) { \
+ BLKC_XLOAD(PRE, ctx->a, ctx->b); \
+ pre##_eblk(&ctx->k, ctx->a, ctx->a); \
+ ctx->off = 0; \
+ } \
+ \
+ /* Now to process the main body of the input. */ \
+ while (plan.from_input) { \
+ BLKC_BSTEP(PRE, ctx->c); pre##_eblk(&ctx->k, ctx->c, t); \
+ BLKC_LOAD(PRE, u, p); p += PRE##_BLKSZ; \
+ BLKC_XSTORE(PRE, q, t, u); q += PRE##_BLKSZ; \
+ BLKC_XMOVE(PRE, ctx->a, u); pre##_eblk(&ctx->k, ctx->a, ctx->a); \
+ plan.from_input -= PRE##_BLKSZ; \
+ } \
+ \
+ /* Finally, deal with any final portion. If there is one, we know \
+ * that the buffer is empty: we must have filled it above, or this \
+ * would all count as `initial' data. \
+ */ \
+ if (plan.tail) { \
+ BLKC_BSTEP(PRE, ctx->c); pre##_eblk(&ctx->k, ctx->c, t); \
+ BLKC_STORE(PRE, ctx->b, t); \
+ r = ctx->b; ctx->off = plan.tail; \
+ while (plan.tail--) { y = *p++; *q++ = y ^ *r; *r++ = y; } \
+ } \
+ \
+ /* Done. */ \
+ return (0); \
+} \
+ \
+/* --- @pre_ccmdecrypt@ --- * \
+ * \
+ * Arguments: @pre_ccmctx *ctx@ = pointer to CCM operation context \
+ * @const void *src@ = pointer to ciphertext message chunk \
+ * @size_t sz@ = size of the ciphertext \
+ * @buf *dst@ = a buffer to write the plaintext to \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Decrypts a chunk of a ciphertext message, writing a \
+ * chunk of plaintext to the output buffer and updating \
+ * the operation state. \
+ * \
+ * For CCM, we always write a plaintext chunk the same \
+ * size as the ciphertext. The messing about with @buf@ \
+ * objects makes the interface consistent with other AEAD \
+ * schemes which can't do this. \
+ */ \
+ \
+int pre##_ccmdecrypt(pre##_ccmctx *ctx, \
+ const void *src, size_t sz, buf *dst) \
+{ \
+ rsvr_plan plan; \
+ uint32 t[PRE##_BLKSZ/4]; \
+ const octet *p = src; \
+ octet *q, *r, y; \
+ \
+ /* Allocate space for the plaintext. */ \
+ if (sz) { q = buf_get(dst, sz); if (!q) return (-1); } \
+ else q = 0; \
+ \
+ /* Set stuff up. */ \
+ pre##_ccmencdecsetup(ctx, sz); \
+ \
+ /* Determine the buffering plan. Our buffer is going to do double- \
+ * duty here. The end portion is going to contain mask from the \
+ * encrypted counter which we mix into the plaintext to encrypt it; \
+ * the start portion, which originally mask bytes we've already used, \
+ * will hold the recovered plaintext, which will eventually be \
+ * collected into the CBC-MAC state. \
+ */ \
+ rsvr_mkplan(&plan, &pre##_ccmpolicy, ctx->off, sz); \
+ \
+ /* Initial portion, fulfilled from the buffer. If the buffer is \
+ * empty, then that means that we haven't yet encrypted the current \
+ * counter, so we should do that and advance it. \
+ */ \
+ if (plan.head) { \
+ if (!ctx->off) { \
+ BLKC_BSTEP(PRE, ctx->c); pre##_eblk(&ctx->k, ctx->c, t); \
+ BLKC_STORE(PRE, ctx->b, t); \
+ } \
+ r = ctx->b + ctx->off; ctx->off += plan.head; \
+ while (plan.head--) { y = *p++ ^ *r; *q++ = *r++ = y; } \
+ } \
+ \
+ /* If we've filled up the buffer then we need to cycle the MAC and \
+ * reset the offset. \
+ */ \
+ if (plan.from_rsvr) { \
+ BLKC_XLOAD(PRE, ctx->a, ctx->b); \
+ pre##_eblk(&ctx->k, ctx->a, ctx->a); \
+ ctx->off = 0; \
+ } \
+ \
+ /* Now to process the main body of the input. */ \
+ while (plan.from_input) { \
+ BLKC_BSTEP(PRE, ctx->c); pre##_eblk(&ctx->k, ctx->c, t); \
+ BLKC_XLOAD(PRE, t, p); p += PRE##_BLKSZ; \
+ BLKC_STORE(PRE, q, t); q += PRE##_BLKSZ; \
+ BLKC_XMOVE(PRE, ctx->a, t); pre##_eblk(&ctx->k, ctx->a, ctx->a); \
+ plan.from_input -= PRE##_BLKSZ; \
+ } \
+ \
+ /* Finally, deal with any final portion. If there is one, we know \
+ * that the buffer is empty: we must have filled it above, or this \
+ * would all count as `initial' data. \
+ */ \
+ if (plan.tail) { \
+ BLKC_BSTEP(PRE, ctx->c); pre##_eblk(&ctx->k, ctx->c, t); \
+ BLKC_STORE(PRE, ctx->b, t); \
+ r = ctx->b; ctx->off = plan.tail; \
+ while (plan.tail--) { y = *p++ ^ *r; *q++ = *r++ = y; } \
+ } \
+ \
+ /* Done. */ \
+ return (0); \
+} \
+ \
+/* --- @pre_ccmtag@ --- * \
+ * \
+ * Arguments: @pre_ccmctx *ctx@ = pointer to an CCM context \
+ * @octet *t@ = where to write a (full-length) tag \
+ * @size_t tsz@ = size of the tag (to check) \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Finishes an CCM operation, by calculating the tag. \
+ */ \
+ \
+static void pre##_ccmtag(pre##_ccmctx *ctx, octet *t, size_t tsz) \
+{ \
+ /* Make sure we're in good shape. It's just about possible that \
+ * we're still in the AAD state, but there was no actual message, so \
+ * handle this situation. \
+ */ \
+ switch (ctx->st) { \
+ case CCMST_AAD: \
+ assert(ctx->i == ctx->p.hsz); \
+ assert(!ctx->p.msz); \
+ break; \
+ case CCMST_MSG: \
+ /* hsz already checked in `pre_ccmencdecsetup'. */ \
+ assert(ctx->i == ctx->p.msz); \
+ break; \
+ default: abort(); \
+ } \
+ assert(tsz == ctx->p.tsz); \
+ \
+ /* Pad the final plaintext block out and cycle the block cipher one \
+ * last time. \
+ */ \
+ memset(ctx->b + ctx->off, 0, PRE##_BLKSZ - ctx->off); \
+ BLKC_XLOAD(PRE, ctx->a, ctx->b); \
+ pre##_eblk(&ctx->k, ctx->a, ctx->a); \
+ \
+ /* Mask the CBC-MAC tag (which prevents the standard extension \
+ * attack) and store the result. \
+ */ \
+ BLKC_XSTORE(PRE, t, ctx->a, ctx->s0); \
+} \
+ \
+/* --- @pre_ccmencryptdone@ --- * \
+ * \
+ * Arguments: @pre_ccmctx *ctx@ = pointer to an CCM context \
+ * @buf *dst@ = buffer for remaining ciphertext \
+ * @void *tag@ = where to write the tag \
+ * @size_t tsz@ = length of tag to store \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Completes an CCM encryption operation. The @aad@ \
+ * pointer may be null if there is no additional \
+ * authenticated data. CCM doesn't buffer ciphertext, but \
+ * the output buffer is provided anyway for consistency \
+ * with other AEAD schemes which don't have this property; \
+ * the function will fail if the output buffer is broken. \
+ */ \
+ \
+int pre##_ccmencryptdone(pre##_ccmctx *ctx, buf *dst, \
+ void *tag, size_t tsz) \
+{ \
+ octet t[PRE##_BLKSZ]; \
+ \
+ /* Some initial checks. */ \
+ if (!BOK(dst)) return (-1); \
+ \
+ /* Calculate and return the tag. */ \
+ pre##_ccmtag(ctx, t, tsz); \
+ memcpy(tag, t, tsz); \
+ \
+ /* Done. */ \
+ return (0); \
+} \
+ \
+/* --- @pre_ccmdecryptdone@ --- * \
+ * \
+ * Arguments: @pre_ccmctx *ctx@ = pointer to an CCM context \
+ * @buf *dst@ = buffer for remaining plaintext \
+ * @const void *tag@ = tag to verify \
+ * @size_t tsz@ = length of tag \
+ * \
+ * Returns: @+1@ for complete success; @0@ if tag verification \
+ * failed; @-1@ for other kinds of errors. \
+ * \
+ * Use: Completes an CCM decryption operation. The @aad@ \
+ * pointer may be null if there is no additional \
+ * authenticated data. CCM doesn't buffer plaintext, but \
+ * the output buffer is provided anyway for consistency \
+ * with other AEAD schemes which don't have this property; \
+ * the function will fail if the output buffer is broken. \
+ */ \
+ \
+int pre##_ccmdecryptdone(pre##_ccmctx *ctx, buf *dst, \
+ const void *tag, size_t tsz) \
+{ \
+ octet t[PRE##_BLKSZ]; \
+ \
+ /* Some initial checks. */ \
+ if (!BOK(dst)) return (-1); \
+ \
+ /* Calculate and check the tag. */ \
+ pre##_ccmtag(ctx, t, tsz); \
+ if (!ct_memeq(tag, t, tsz)) return (0); \
+ else return (+1); \
+} \
+ \
+/* --- Generic AEAD interface --- */ \
+ \
+typedef struct gctx { \
+ gaead_aad a; \
+ pre##_ccmctx ctx; \
+} gctx; \
+ \
+static void gahash(gaead_aad *a, const void *h, size_t hsz) \
+ { gctx *ctx = (gctx *)a; pre##_ccmaadhash(&ctx->ctx, h, hsz); } \
+ \
+static void gadestroy(gaead_aad *a) { ; } \
+ \
+static const gaead_aadops gaops = \
+ { &pre##_ccm, 0, gahash, gadestroy }; \
+ \
+typedef struct gectx { \
+ gaead_enc e; \
+ gctx g; \
+} gectx; \
+ \
+static gaead_aad *geaad(gaead_enc *e) \
+ { gectx *enc = (gectx *)e; return (&enc->g.a); } \
+ \
+static int gereinit(gaead_enc *e, const void *n, size_t nsz, \
+ size_t hsz, size_t msz, size_t tsz) \
+{ \
+ gectx *enc = (gectx *)e; \
+ return (pre##_ccmreinit(&enc->g.ctx, n, nsz, hsz, msz, tsz)); \
+} \
+ \
+static int geenc(gaead_enc *e, const void *m, size_t msz, buf *b) \
+{ \
+ gectx *enc = (gectx *)e; \
+ return (pre##_ccmencrypt(&enc->g.ctx, m, msz, b)); \
+} \
+ \
+static int gedone(gaead_enc *e, const gaead_aad *a, \
+ buf *b, void *t, size_t tsz) \
+{ \
+ gectx *enc = (gectx *)e; \
+ assert((!a && !enc->g.ctx.p.hsz) || a == &enc->g.a); \
+ return (pre##_ccmencryptdone(&enc->g.ctx, b, t, tsz)); \
+} \
+ \
+static void gedestroy(gaead_enc *e) \
+ { gectx *enc = (gectx *)e; BURN(*enc); S_DESTROY(enc); } \
+ \
+static const gaead_encops geops = \
+ { &pre##_ccm, geaad, gereinit, geenc, gedone, gedestroy }; \
+ \
+typedef struct gdctx { \
+ gaead_dec d; \
+ gctx g; \
+} gdctx; \
+ \
+static gaead_aad *gdaad(gaead_dec *d) \
+ { gdctx *dec = (gdctx *)d; return (&dec->g.a); } \
+ \
+static int gdreinit(gaead_dec *d, const void *n, size_t nsz, \
+ size_t hsz, size_t csz, size_t tsz) \
+{ \
+ gdctx *dec = (gdctx *)d; \
+ return (pre##_ccmreinit(&dec->g.ctx, n, nsz, hsz, csz, tsz)); \
+} \
+ \
+static int gddec(gaead_dec *d, const void *c, size_t csz, buf *b) \
+{ \
+ gdctx *dec = (gdctx *)d; \
+ return (pre##_ccmdecrypt(&dec->g.ctx, c, csz, b)); \
+} \
+ \
+static int gddone(gaead_dec *d, const gaead_aad *a, \
+ buf *b, const void *t, size_t tsz) \
+{ \
+ gdctx *dec = (gdctx *)d; \
+ assert((!a && !dec->g.ctx.p.hsz) || a == &dec->g.a); \
+ return (pre##_ccmdecryptdone(&dec->g.ctx, b, t, tsz)); \
+} \
+ \
+static void gddestroy(gaead_dec *d) \
+ { gdctx *dec = (gdctx *)d; BURN(*dec); S_DESTROY(dec); } \
+ \
+static const gaead_decops gdops = \
+ { &pre##_ccm, gdaad, gdreinit, gddec, gddone, gddestroy }; \
+ \
+typedef struct gkctx { \
+ gaead_key k; \
+ pre##_ctx key; \
+} gkctx; \
+ \
+static gaead_enc *gkenc(const gaead_key *k, const void *n, size_t nsz, \
+ size_t hsz, size_t msz, size_t tsz) \
+{ \
+ gkctx *key = (gkctx *)k; \
+ gectx *enc = S_CREATE(gectx); \
+ \
+ enc->e.ops = &geops; enc->g.a.ops = &gaops; \
+ if (pre##_ccminit(&enc->g.ctx, &key->key, n, nsz, hsz, msz, tsz)) \
+ { gedestroy(&enc->e); return (0); } \
+ return (&enc->e); \
+} \
+ \
+static gaead_dec *gkdec(const gaead_key *k, const void *n, size_t nsz, \
+ size_t hsz, size_t csz, size_t tsz) \
+{ \
+ gkctx *key = (gkctx *)k; \
+ gdctx *dec = S_CREATE(gdctx); \
+ \
+ dec->d.ops = &gdops; dec->g.a.ops = &gaops; \
+ if (pre##_ccminit(&dec->g.ctx, &key->key, n, nsz, hsz, csz, tsz)) \
+ { gddestroy(&dec->d); return (0); } \
+ return (&dec->d); \
+} \
+ \
+static void gkdestroy(gaead_key *k) \
+ { gkctx *key = (gkctx *)k; BURN(*key); S_DESTROY(key); } \
+ \
+static const gaead_keyops gkops = \
+ { &pre##_ccm, 0, gkenc, gkdec, gkdestroy }; \
+ \
+static gaead_key *gckey(const void *k, size_t ksz) \
+{ \
+ gkctx *key = S_CREATE(gkctx); \
+ key->k.ops = &gkops; \
+ pre##_init(&key->key, k, ksz); \
+ return (&key->k); \
+} \
+ \
+const gcaead pre##_ccm = { \
+ name "-ccm", \
+ pre##_keysz, pre##_ccmnoncesz, pre##_ccmtagsz, \
+ PRE##_BLKSZ, 0, 0, \
+ AEADF_PCHSZ | AEADF_PCMSZ | AEADF_PCTSZ | \
+ AEADF_AADNDEP | AEADF_AADFIRST, \
+ gckey \
+}; \
+ \
+CCM_TESTX(PRE, pre, name, fname)
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#define CCM_TEST(PRE, pre) CCM_TESTX(PRE, pre, #pre, #pre)
+
+/* --- @CCM_TEST@ --- *
+ *
+ * Arguments: @PRE, pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Standard test rig for CCM functions.
+ */
+
+#ifdef TEST_RIG
+
+#include <stdio.h>
+
+#include <mLib/dstr.h>
+#include <mLib/quis.h>
+#include <mLib/testrig.h>
+
+#define CCM_TESTX(PRE, pre, name, fname) \
+ \
+static int ccmverify(dstr *v) \
+{ \
+ pre##_ctx key; \
+ pre##_ccmctx ctx; \
+ int ok = 1, win; \
+ int i; \
+ octet *p; \
+ int szs[] = { 1, 7, 192, -1, 0 }, *ip; \
+ size_t hsz, msz; \
+ dstr d = DSTR_INIT, t = DSTR_INIT; \
+ buf b; \
+ \
+ dstr_ensure(&d, v[4].len > v[3].len ? v[4].len : v[3].len); \
+ dstr_ensure(&t, v[5].len); t.len = v[5].len; \
+ \
+ pre##_init(&key, v[0].buf, v[0].len); \
+ \
+ for (ip = szs; *ip; ip++) { \
+ \
+ pre##_ccminit(&ctx, &key, (octet *)v[1].buf, v[1].len, \
+ v[2].len, v[3].len, v[5].len); \
+ \
+ i = *ip; \
+ hsz = v[2].len; \
+ if (i == -1) i = hsz; \
+ if (i > hsz) continue; \
+ p = (octet *)v[2].buf; \
+ while (hsz) { \
+ if (i > hsz) i = hsz; \
+ pre##_ccmaadhash(&ctx, p, i); \
+ p += i; hsz -= i; \
+ } \
+ \
+ buf_init(&b, d.buf, d.sz); \
+ i = *ip; \
+ msz = v[3].len; \
+ if (i == -1) i = msz; \
+ if (i > msz) continue; \
+ p = (octet *)v[3].buf; \
+ while (msz) { \
+ if (i > msz) i = msz; \
+ if (pre##_ccmencrypt(&ctx, p, i, &b)) { \
+ puts("!! ccmencrypt reports failure"); \
+ goto fail_enc; \
+ } \
+ p += i; msz -= i; \
+ } \
+ \
+ if (pre##_ccmencryptdone(&ctx, &b, (octet *)t.buf, t.len)) { \
+ puts("!! ccmencryptdone reports failure"); \
+ goto fail_enc; \
+ } \
+ d.len = BLEN(&b); \
+ \
+ if (d.len != v[4].len || \
+ memcmp(d.buf, v[4].buf, v[4].len) != 0 || \
+ memcmp(t.buf, v[5].buf, v[5].len) != 0) { \
+ fail_enc: \
+ printf("\nfail encrypt:\n\tstep = %i", *ip); \
+ fputs("\n\tkey = ", stdout); type_hex.dump(&v[0], stdout); \
+ fputs("\n\tnonce = ", stdout); type_hex.dump(&v[1], stdout); \
+ fputs("\n\theader = ", stdout); type_hex.dump(&v[2], stdout); \
+ fputs("\n\tmessage = ", stdout); type_hex.dump(&v[3], stdout); \
+ fputs("\n\texp ct = ", stdout); type_hex.dump(&v[4], stdout); \
+ fputs("\n\tcalc ct = ", stdout); type_hex.dump(&d, stdout); \
+ fputs("\n\texp tag = ", stdout); type_hex.dump(&v[5], stdout); \
+ fputs("\n\tcalc tag = ", stdout); type_hex.dump(&t, stdout); \
+ putchar('\n'); \
+ ok = 0; \
+ } \
+ \
+ pre##_ccminit(&ctx, &key, (octet *)v[1].buf, v[1].len, \
+ v[2].len, v[4].len, v[5].len); \
+ \
+ i = *ip; \
+ hsz = v[2].len; \
+ if (i == -1) i = hsz; \
+ if (i > hsz) continue; \
+ p = (octet *)v[2].buf; \
+ while (hsz) { \
+ if (i > hsz) i = hsz; \
+ pre##_ccmaadhash(&ctx, p, i); \
+ p += i; hsz -= i; \
+ } \
+ \
+ buf_init(&b, d.buf, d.sz); \
+ i = *ip; \
+ msz = v[4].len; \
+ if (i == -1) i = msz; \
+ if (i > msz) continue; \
+ p = (octet *)v[4].buf; \
+ while (msz) { \
+ if (i > msz) i = msz; \
+ if (pre##_ccmdecrypt(&ctx, p, i, &b)) { \
+ puts("!! ccmdecrypt reports failure"); \
+ win = 0; goto fail_dec; \
+ } \
+ p += i; msz -= i; \
+ } \
+ \
+ win = pre##_ccmdecryptdone(&ctx, &b, (octet *)v[5].buf, v[5].len); \
+ if (win < 0) { \
+ puts("!! ccmdecryptdone reports failure"); \
+ goto fail_dec; \
+ } \
+ d.len = BLEN(&b); \
+ \
+ if (d.len != v[3].len || !win || \
+ memcmp(d.buf, v[3].buf, v[3].len) != 0) { \
+ fail_dec: \
+ printf("\nfail decrypt:\n\tstep = %i", *ip); \
+ fputs("\n\tkey = ", stdout); type_hex.dump(&v[0], stdout); \
+ fputs("\n\tnonce = ", stdout); type_hex.dump(&v[1], stdout); \
+ fputs("\n\theader = ", stdout); type_hex.dump(&v[2], stdout); \
+ fputs("\n\tciphertext = ", stdout); type_hex.dump(&v[4], stdout); \
+ fputs("\n\texp pt = ", stdout); type_hex.dump(&v[3], stdout); \
+ fputs("\n\tcalc pt = ", stdout); type_hex.dump(&d, stdout); \
+ fputs("\n\ttag = ", stdout); type_hex.dump(&v[5], stdout); \
+ printf("\n\tverify %s", win ? "ok" : "FAILED"); \
+ putchar('\n'); \
+ ok = 0; \
+ } \
+ } \
+ \
+ dstr_destroy(&d); dstr_destroy(&t); \
+ return (ok); \
+} \
+ \
+static test_chunk aeaddefs[] = { \
+ { name "-ccm", ccmverify, \
+ { &type_hex, &type_hex, &type_hex, &type_hex, \
+ &type_hex, &type_hex, 0 } }, \
+ { 0, 0, { 0 } } \
+}; \
+ \
+int main(int argc, char *argv[]) \
+{ \
+ ego(argv[0]); \
+ test_run(argc, argv, aeaddefs, SRCDIR"/t/" fname); \
+ return (0); \
+}
+
+#else
+# define CCM_TESTX(PRE, pre, name, fname)
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
--- /dev/null
+/* -*-c-*-
+ *
+ * CCM common code
+ *
+ * (c) 2018 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "ccm.h"
+#include "ccm-def.h"
+
+/*----- MAC header and counter formatting ---------------------------------*
+ *
+ * CCM's most endearing feature is its complex formatting of the MAC
+ * initialization vector and counter blocks. This is only specified for
+ * 128-bit blocks, so I've made up formats for 64-, 192-, and 256-bit blocks.
+ * For completeness and ease of comparison, all of the encodings are defined
+ * here. Encoding of the rest of the MAC input data is common.
+ *
+ * The notation is taken from the definition of CCM in NIST SP800-38C.
+ *
+ * * [x]_w = encoding of x, as w bits
+ * * P = plaintext/ciphertext
+ * * p = length of P in octets
+ * * Q = [p]_{8q} = encoding of p
+ * * q = length of Q in octets
+ * * N = nonce
+ * * H = B_0 = MAC header block
+ * * C_i = the i-th counter block
+ * * t = length of tag in octets
+ *
+ * 128-bit blocks (SP800-38C, appendix A):
+ *
+ * Let F be an octet:
+ *
+ * Bits 7 6 6:3 3:0
+ * Meaning 0 AAD? [t/2 - 1]_3 [q - 1]_3
+ *
+ * Then H = F || N || Q and C_i = 0^5 || [q - 1]_3 || N || [i]_{8q}.
+ *
+ * 64-bit blocks (new):
+ *
+ * Let F be an octet:
+ *
+ * Bits 7 6 6:3 3:0
+ * Meaning 0 AAD? [t - 1]_3 [q - 1]_3
+ *
+ * Then H = F || N || Q and C_i = 0^5 || [q - 1]_3 || N || [i]_{8q}.
+ *
+ * (i.e., almost exactly the same, except that the tag no longer needs to be
+ * an even number of octets).
+ *
+ * n-bit blocks, for n > 128
+ *
+ * Let F be a 16-bit flags word:
+ *
+ * Bits 15 15:8 7 7:0
+ * Meaning 0 [t]_7 AAD? [q]_7
+ *
+ * Then H = F || N || Q and C_i = 0^9 || [q - 1]_7 || N || [i]_{8q}.
+ */
+
+/* --- @ccm_paramsok@ --- *
+ *
+ * Arguments: @const ccm_params *p@ = pointer to parameters
+ *
+ * Returns: True (nonzero) if the parameters are OK; false (zero) if
+ * there's a problem.
+ *
+ * Use: Verify that the CCM parameters are acceptable.
+ */
+
+int ccm_check(const ccm_params *p)
+{
+ unsigned fsz = p->bsz <= 16 ? 1 : 2, q = p->bsz - p->nsz - fsz, i;
+ size_t msz;
+
+ /* Check that the block size hasn't been bungled. */
+ if (p->bsz < 16 && p->bsz != 8) return (0);
+
+ /* The length-of-the-length must be representable, and its encoding must
+ * not be zero, since this is `reserved'. The small-block encoding stores
+ * %$q - 1$%, so we must have %$q \ge 2$%; the large-block encoding stores
+ * %$q$% directly, so only %$q = 0$% is forbidden.
+ */
+ if (p->nsz > p->bsz - fsz - (p->bsz <= 16 ? 2 : 1)) return (0);
+ if (q > (p->bsz <= 16 ? 8 : 127)) return (0);
+
+ /* Verify that the message length will fit in the space allotted. */
+ for (i = 1, msz = p->msz >> 8; msz; i++, msz >>= 8);
+ if (i > q) return (0);
+
+ /* The tag can't be larger than the block size. Also, it must be
+ * representable, and its encoding must not be zero, because otherwise it'd
+ * be possible for a MAC header block to look like a counter block. The
+ * tag encoding is fiddly: for 64-bit blocks, we store %$t - 1$%, so we
+ * must have %$t \ge 2$%; for 128-bit blocks, we store %$t/2 - 2$%, so
+ * we must have %$t \ge 4$% with %$t$% even; otherwise, we store %$t$%
+ * directly, so the only requirement is that %$t \ge 1$%.
+ */
+ if (p->tsz > p->bsz) return (0);
+ if (p->tsz < (p->bsz == 8 ? 2 : p->bsz == 16 ? 4 : 1)) return (0);
+ if (p->bsz == 16 && p->tsz%2 != 0) return (0);
+
+ /* All looks good. */
+ return (1);
+}
+
+/* --- @ccm_fmthdr@ --- *
+ *
+ * Arguments: @const ccm_params *p@ = pointer to parameters
+ * @octet *b@ = block-size buffer to write header
+ * @const void *n@ = pointer to nonce
+ *
+ * Returns: ---
+ *
+ * Use: Format a MAC header block.
+ */
+
+void ccm_fmthdr(const ccm_params *p, octet *b, const void *n)
+{
+ size_t fsz = p->bsz <= 16 ? 1 : 2, q = p->bsz - p->nsz - fsz;
+ unsigned f0 = 0, f1 = 0;
+ size_t i, t;
+
+ /* Encode whether the AAD is empty. */
+ if (!p->hsz) /* do nothing */;
+ else if (p->bsz <= 16) f0 |= 0x40;
+ else f1 |= 0x80;
+
+ /* Encode the tag size. */
+ switch (p->bsz) {
+ case 8: f0 |= (p->tsz - 1) << 3; break;
+ case 16: f0 |= (p->tsz - 2) << 2; break;
+ default: f0 |= p->tsz; break;
+ }
+
+ /* Encode the length-of-the-length. (This is the most bletcherous part of
+ * CCM.)
+ */
+ if (p->bsz <= 16) f0 |= q - 1;
+ else f1 |= q;
+
+ /* Insert the flags and nonce. */
+ b[0] = f0; memcpy(b + fsz, n, p->nsz);
+ if (p->bsz > 16) b[1] = f1;
+
+ /* Write the message length. */
+ for (i = 0, t = p->msz; i < q; i++, t >>= 8) b[p->bsz - i - 1] = U8(t);
+}
+
+/* --- @ccm_fmtctr@ --- *
+ *
+ * Arguments: @const ccm_params *p@ = pointer to parameters
+ * @octet *b@ = block-size buffer to write header
+ * @const void *n@ = pointer to nonce
+ *
+ * Returns: ---
+ *
+ * Use: Format an initial counter block.
+ */
+
+void ccm_fmtctr(const ccm_params *p, octet *b, const void *n)
+{
+ size_t fsz = p->bsz <= 16 ? 1 : 2, q = p->bsz - p->nsz - fsz;
+ unsigned f0 = 0, f1 = 0;
+
+ /* Encode the message length length. (Did I complain about this?) */
+ if (p->bsz <= 16) f0 |= q - 1;
+ else f1 |= q;
+
+ /* Insert the flags and nonce. */
+ b[0] = f0; memcpy(b + fsz, n, p->nsz);
+ if (p->bsz > 16) b[1] = f1;
+
+ /* Zero out the initial counter. */
+ memset(b + fsz + p->nsz, 0, q);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
--- /dev/null
+/* -*-c-*-
+ *
+ * The CCM authenticated-encryption mode
+ *
+ * (c) 2017 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Notes on CCM ------------------------------------------------------*
+ *
+ * The name is short for `Counter with CBC-MAC'. CCM was designed in 2002 by
+ * Russ Housley, Doug Whiting, and Niels Ferguson to be a patent-free
+ * alternative to Rogaway's OCB, and is specified by NIST in SP800-38C. It's
+ * a classic two-pass authenticated encryption scheme, so it needs two
+ * blockcipher applications per message block.
+ *
+ * Unfortunately, CCM is rather annoying in actual use. The internals
+ * involve quite a lot of fiddly framing, which I've had to generalize for
+ * block sizes other than 128 bits, but that's not exposed beyond the API.
+ * (This does mean that it's rather unlikely that Catacomb's CCM will
+ * interoperate with anyone else's when using a blockcipher with a block size
+ * other than 128 bits.)
+ *
+ * More problematically:
+ *
+ * * The mode requires that callers precommit to the header, message, and
+ * tag sizes before commencing processing. If you don't know these in
+ * advance then you can't use CCM.
+ *
+ * * The mode requires that callers present all of the header data before
+ * encrypting the message.
+ *
+ * * The header data processing is dependent on the nonce (and the message
+ * and tag lengths), so it's not possible to preprocess a constant prefix
+ * of the header.
+ *
+ * * There's an uncomfortable tradeoff between nonce length and message
+ * length because the counter input holds both in separate fields, with a
+ * variably-positioned split between them.
+ *
+ * The implementation is very picky and will abort if you get things wrong.
+ */
+
+#ifndef CATACOMB_CCM_H
+#define CATACOMB_CCM_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+#include <mLib/buf.h>
+
+#ifndef CATACOMB_GAEAD_H
+# include "gaead.h"
+#endif
+
+/*----- Common machinery -------------------------------------------------*/
+
+typedef struct ccm_params {
+ unsigned long hsz, msz; /* AAD and message lengths */
+ unsigned bsz, nsz, tsz; /* Block, nonce and tag length */
+} ccm_params;
+
+enum { CCMST_AAD, CCMST_MSG };
+
+/* Minimum and maximum nonce lengths.
+ *
+ * Let the block size be %$N$% bytes, and let %$q$% be the length-of-the-
+ * length of the messaage. The nonce length is not encoded directly; rather,
+ * it's what's left after the flags bytes and message length fields have been
+ * allocated.
+ *
+ * The maximum is always %$N - 3$%. If %$N \le 16$%, then there is one byte
+ * used for flags, and at least two bytes for the message length/counter:
+ * (since %$q$% is encoded in a 3-bit field as %$q - 1$%, %$q = 0$% cannot be
+ * encoded and the encoding zero, for %$q = 1$%, is reserved. If %$N > 16$
+ * then there are two flags bytes, but %$q$% is encoded directly, so only
+ * %$q = 0$% is reserved.
+ *
+ * The minimum is more complicated. If %$N \le 16$% then we must have %$q
+ * \le 8$%; with one flags byte, this leaves at least %$\max\{ 0, N - 9 \}$%
+ * bytes for the nonce. When %$N = 8$% this is zero, but when %$N = 16$%
+ * this is 7. When %$N > 16$%, there are two flags bits, but %$q \le 127$%
+ * (since %$q$%) is encoded directly: thus the nonce may be empty if
+ * %$16 < N \le 129$%, and otherwise must be at least %$N - 129$% bytes.
+ */
+#define CCM_NSZMIN(PRE) (PRE##_BLKSZ == 16 ? 7 : \
+ PRE##_BLKSZ <= 129 ? 0 : \
+ PRE##_BLKSZ - 129)
+#define CCM_NSZMAX(PRE) (PRE##_BLKSZ - 3)
+
+/* Minimum and maximum tag lengths.
+ *
+ * This is even more exasperating. Again, let the block size be %$N$% bytes;
+ * let %$t$% be the tag length.
+ *
+ * When %$N = 16$%, the tag length is encoded as %$t/2 - 1$% in a three-bit
+ * field, and the encoding zero is reserved. (The security of the scheme
+ * depends on this reservation to disambiguate MAC header blocks from
+ * counters; I'd have used the remaining flag bit.) Anyway, this leaves
+ * %$1 \le t/2 - 1 \le 7$%, so we must have %$4 \le t \le 16$% with %$t$%
+ * even.
+ *
+ * When %$N = 8$%, the tag length is encoded in three bits as %$t - 1$%;
+ * again, the zero encoding is reserved. This leaves %$2 \le t \le 8$%.
+ *
+ * Finally, when %$N \ge 16$%, the tag length is encoded directly in a
+ * seven-bit field. The zero encoding is still reserved, so we have
+ * %$1 \le t \le \min \{ N, 127 \}$%.
+ */
+#define CCM_TSZMIN(PRE) (PRE##_BLKSZ == 8 ? 2 : \
+ PRE##_BLKSZ == 16 ? 4 : \
+ 1)
+#define CCM_TSZMAX(PRE) (PRE##_BLKSZ <= 127 ? PRE##_BLKSZ : 127)
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @CCM_DECL@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Creates declarations for CCM authenticated-encryption mode.
+ */
+
+#define CCM_DECL(PRE, pre) \
+ \
+typedef struct pre##_ccmctx { \
+ /* The buffer is split into two portions during encryption/ \
+ * decryption. The first N octets hold a chunk of plaintext, which \
+ * will be fed into the CBC-MAC calculation; the remaining BLKSZ - N \
+ * octets hold E_K(C), which is the XOR mask to apply to the \
+ * plaintext or ciphertext. \
+ */ \
+ pre##_ctx k; /* Underlying key */ \
+ ccm_params p; /* CCM parameters */ \
+ unsigned long i; /* Current position in bytes */ \
+ unsigned st; /* Current state */ \
+ uint32 c[PRE##_BLKSZ/4]; /* Current counter value */ \
+ uint32 a[PRE##_BLKSZ/4]; /* CBC-MAC accumulator */ \
+ uint32 s0[PRE##_BLKSZ/4]; /* Mask for MAC tag */ \
+ octet b[PRE##_BLKSZ]; /* AAD or msg/mask buffer */ \
+ unsigned off; /* Crossover point in buffer */ \
+} pre##_ccmctx; \
+ \
+extern const octet pre##_ccmnoncesz[], pre##_ccmtagsz[]; \
+ \
+/* --- @pre_ccminit@ --- * \
+ * \
+ * Arguments: @pre_ccmctx *aad@ = pointer to CCM context \
+ * @const pre_ctx *k@ = pointer to key material \
+ * @const void *n@ = pointer to nonce \
+ * @size_t nsz@ = size of the nonce \
+ * @size_t hsz@ = size of the AAD \
+ * @size_t msz@ = size of the message/ciphertext \
+ * @size_t tsz@ = size of the tag to produce \
+ * \
+ * Returns: Zero on success; nonzero if the parameters are invalid. \
+ * \
+ * Use: Initialize an CCM operation context with a given key. \
+ * \
+ * The original key needn't be kept around any more. \
+ */ \
+ \
+extern int pre##_ccminit(pre##_ccmctx */*ctx*/, \
+ const pre##_ctx */*k*/, \
+ const void */*n*/, size_t /*nsz*/, \
+ size_t /*hsz*/, size_t /*msz*/, \
+ size_t /*tsz*/); \
+ \
+/* --- @pre_ccmreinit@ --- * \
+ * \
+ * Arguments: @pre_ccmctx *ctx@ = pointer to CCM context \
+ * @const void *n@ = pointer to nonce \
+ * @size_t nsz@ = size of nonce \
+ * @size_t hsz@ = size of the AAD \
+ * @size_t msz@ = size of the message/ciphertext \
+ * @size_t tsz@ = size of the tag to produce \
+ * \
+ * Returns: Zero on success; nonzero if the parameters are invalid. \
+ * \
+ * Use: Reinitialize an CCM operation context, changing the \
+ * nonce and/or other parameters. \
+ */ \
+ \
+extern int pre##_ccmreinit(pre##_ccmctx */*ctx*/, \
+ const void */*n*/, size_t /*nsz*/, \
+ size_t /*hsz*/, size_t /*msz*/, \
+ size_t /*tsz*/); \
+ \
+/* --- @pre_ccmaadhash@ --- * \
+ * \
+ * Arguments: @pre_ccmctx *ctx@ = pointer to AAD context \
+ * @const void *p@ = pointer to AAD material \
+ * @size_t sz@ = length of AAD material \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Feeds AAD into the context. This must be done before \
+ * any of the message/ciphertext is processed because CCM \
+ * is really annoying like that. \
+ */ \
+ \
+extern void pre##_ccmaadhash(pre##_ccmctx */*ctx*/, \
+ const void */*p*/, size_t /*sz*/); \
+ \
+/* --- @pre_ccmencrypt@ --- * \
+ * \
+ * Arguments: @pre_ccmctx *ctx@ = pointer to CCM operation context \
+ * @const void *src@ = pointer to plaintext message chunk \
+ * @size_t sz@ = size of the plaintext \
+ * @buf *dst@ = a buffer to write the ciphertext to \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Encrypts a chunk of a plaintext message, writing a \
+ * chunk of ciphertext to the output buffer and updating \
+ * the operation state. \
+ * \
+ * For CCM, we always write a ciphertext chunk the same \
+ * size as the plaintext. The messing about with @buf@ \
+ * objects makes the interface consistent with other AEAD \
+ * schemes which can't do this. \
+ */ \
+ \
+extern int pre##_ccmencrypt(pre##_ccmctx */*ctx*/, \
+ const void */*src*/, size_t /*sz*/, \
+ buf */*dst*/); \
+ \
+/* --- @pre_ccmdecrypt@ --- * \
+ * \
+ * Arguments: @pre_ccmctx *ctx@ = pointer to CCM operation context \
+ * @const void *src@ = pointer to ciphertext message chunk \
+ * @size_t sz@ = size of the ciphertext \
+ * @buf *dst@ = a buffer to write the plaintext to \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Decrypts a chunk of a ciphertext message, writing a \
+ * chunk of plaintext to the output buffer and updating \
+ * the operation state. \
+ * \
+ * For CCM, we always write a plaintext chunk the same \
+ * size as the ciphertext. The messing about with @buf@ \
+ * objects makes the interface consistent with other AEAD \
+ * schemes which can't do this. \
+ */ \
+ \
+extern int pre##_ccmdecrypt(pre##_ccmctx */*ctx*/, \
+ const void */*src*/, size_t /*sz*/, \
+ buf */*dst*/); \
+ \
+/* --- @pre_ccmencryptdone@ --- * \
+ * \
+ * Arguments: @pre_ccmctx *ctx@ = pointer to an CCM context \
+ * @buf *dst@ = buffer for remaining ciphertext \
+ * @void *tag@ = where to write the tag \
+ * @size_t tsz@ = length of tag to store \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Completes an CCM encryption operation. The @aad@ \
+ * pointer may be null if there is no additional \
+ * authenticated data. CCM doesn't buffer ciphertext, but \
+ * the output buffer is provided anyway for consistency \
+ * with other AEAD schemes which don't have this property; \
+ * the function will fail if the output buffer is broken. \
+ */ \
+ \
+extern int pre##_ccmencryptdone(pre##_ccmctx */*ctx*/, buf */*dst*/, \
+ void */*tag*/, size_t /*tsz*/); \
+ \
+/* --- @pre_ccmdecryptdone@ --- * \
+ * \
+ * Arguments: @pre_ccmctx *ctx@ = pointer to an CCM context \
+ * @buf *dst@ = buffer for remaining plaintext \
+ * @const void *tag@ = tag to verify \
+ * @size_t tsz@ = length of tag \
+ * \
+ * Returns: @+1@ for complete success; @0@ if tag verification \
+ * failed; @-1@ for other kinds of errors. \
+ * \
+ * Use: Completes an CCM decryption operation. The @aad@ \
+ * pointer may be null if there is no additional \
+ * authenticated data. CCM doesn't buffer plaintext, but \
+ * the output buffer is provided anyway for consistency \
+ * with other AEAD schemes which don't have this property; \
+ * the function will fail if the output buffer is broken. \
+ */ \
+ \
+extern int pre##_ccmdecryptdone(pre##_ccmctx */*ctx*/, buf */*dst*/, \
+ const void */*tag*/, size_t /*tsz*/); \
+ \
+/* --- Generic AEAD interface --- */ \
+ \
+extern const gcaead pre##_ccm;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
# include "paranoia.h"
#endif
+#ifndef CATACOMB_RSVR_H
+# include "rsvr.h"
+#endif
+
/*----- Macros ------------------------------------------------------------*/
/* --- @CFB_DEF@ --- *
octet *p = iv; \
unsigned off = ctx->off; \
unsigned rest = PRE##_BLKSZ - off; \
- memcpy(p, ctx->iv + off, rest); \
- memcpy(p + rest, ctx->iv, off); \
+ \
+ memcpy(p, ctx->b + off, rest); \
+ memcpy(p + rest, ctx->b, off); \
} \
\
/* --- @pre_cfbsetiv@ --- * \
*/ \
\
void pre##_cfbsetiv(pre##_cfbctx *ctx, const void *iv) \
-{ \
- memcpy(ctx->iv, iv, PRE##_BLKSZ); \
- ctx->off = PRE##_BLKSZ; \
-} \
+ { memcpy(ctx->b, iv, PRE##_BLKSZ); ctx->off = 0; } \
\
/* --- @pre_cfbbdry@ --- * \
* \
\
void pre##_cfbbdry(pre##_cfbctx *ctx) \
{ \
- uint32 niv[PRE##_BLKSZ / 4]; \
- BLKC_LOAD(PRE, niv, ctx->iv); \
- pre##_eblk(&ctx->ctx, niv, niv); \
- BLKC_STORE(PRE, ctx->iv, niv); \
- ctx->off = PRE##_BLKSZ; \
- BURN(niv); \
+ uint32 t[PRE##_BLKSZ/4]; \
+ \
+ BLKC_LOAD(PRE, t, ctx->b); \
+ pre##_eblk(&ctx->ctx, t, t); \
+ BLKC_STORE(PRE, ctx->b, t); \
+ ctx->off = 0; \
+ BURN(t); \
} \
\
/* --- @pre_cfbsetkey@ --- * \
*/ \
\
void pre##_cfbsetkey(pre##_cfbctx *ctx, const pre##_ctx *k) \
-{ \
- ctx->ctx = *k; \
- ctx->off = PRE##_BLKSZ; \
-} \
+ { ctx->ctx = *k; ctx->off = 0; } \
\
/* --- @pre_cfbinit@ --- * \
* \
*/ \
\
void pre##_cfbinit(pre##_cfbctx *ctx, \
- const void *key, size_t sz, \
- const void *iv) \
+ const void *key, size_t sz, \
+ const void *iv) \
{ \
static const octet zero[PRE##_BLKSZ] = { 0 }; \
+ \
pre##_init(&ctx->ctx, key, sz); \
pre##_cfbsetiv(ctx, iv ? iv : zero); \
} \
* sensitive to block boundaries. \
*/ \
\
+static const rsvr_policy pre##_cfbpolicy = { 0, PRE##_BLKSZ, PRE##_BLKSZ }; \
+ \
void pre##_cfbencrypt(pre##_cfbctx *ctx, \
- const void *src, void *dest, \
- size_t sz) \
+ const void *src, void *dest, \
+ size_t sz) \
{ \
+ rsvr_plan plan; \
const octet *s = src; \
- octet *d = dest; \
- unsigned off = ctx->off; \
- \
- /* --- Empty blocks are trivial --- */ \
- \
- if (!sz) \
- return; \
- \
- /* --- If I can deal with the block from my buffer, do that --- */ \
- \
- if (sz < PRE##_BLKSZ - off) \
- goto small; \
- \
- /* --- Finish off what's left in my buffer --- */ \
- \
- while (off < PRE##_BLKSZ) { \
- register octet x = *s++; \
- ctx->iv[off] ^= x; \
- if (d) *d++ = ctx->iv[off]; \
- off++; \
- sz--; \
+ octet *d = dest, *p; \
+ uint32 t[PRE##_BLKSZ/4]; \
+ octet y; \
+ \
+ /* Construct a plan and prepare to follow through. */ \
+ rsvr_mkplan(&plan, &pre##_cfbpolicy, ctx->off, sz); \
+ BLKC_LOAD(PRE, t, ctx->b); \
+ \
+ /* Initial portion, fulfilled from the buffer. If the chunk is small \
+ * enough, then this will be the only portion. If the buffer is \
+ * currently empty, then we must prepare it. \
+ */ \
+ if (plan.head) { \
+ if (!ctx->off) { \
+ pre##_eblk(&ctx->ctx, t, t); \
+ BLKC_STORE(PRE, ctx->b, t); \
+ } \
+ p = ctx->b + ctx->off; ctx->off += plan.head; \
+ if (s) while (plan.head--) { y = *s++ ^ *p; *p++ = y; if (d) *d++ = y; } \
+ else if (d) { memcpy(d, p, plan.head); d += plan.head; } \
+ BLKC_LOAD(PRE, t, ctx->b); \
} \
\
- /* --- Main encryption loop --- */ \
- \
- { \
- uint32 iv[PRE##_BLKSZ / 4]; \
- BLKC_LOAD(PRE, iv, ctx->iv); \
- \
- for (;;) { \
- pre##_eblk(&ctx->ctx, iv, iv); \
- if (sz < PRE##_BLKSZ) \
- break; \
- if (s) { \
- BLKC_XLOAD(PRE, iv, s); \
- s += PRE##_BLKSZ; \
- } \
- if (d) { \
- BLKC_STORE(PRE, d, iv); \
- d += PRE##_BLKSZ; \
- } \
- sz -= PRE##_BLKSZ; \
+ /* If the buffer is all used, then reset it ready for next time. */ \
+ ctx->off -= plan.from_rsvr; \
+ \
+ /* Handle multiple whole blocks. */ \
+ if (!d) { \
+ if (!s) while (plan.from_input) { \
+ pre##_eblk(&ctx->ctx, t, t); \
+ plan.from_input -= PRE##_BLKSZ; \
+ } else while (plan.from_input) { \
+ pre##_eblk(&ctx->ctx, t, t); \
+ BLKC_XLOAD(PRE, t, s); s += PRE##_BLKSZ; \
+ plan.from_input -= PRE##_BLKSZ; \
+ } \
+ } else { \
+ if (!s) while (plan.from_input) { \
+ pre##_eblk(&ctx->ctx, t, t); \
+ BLKC_STORE(PRE, d, t); d += PRE##_BLKSZ; \
+ plan.from_input -= PRE##_BLKSZ; \
+ } else while (plan.from_input) { \
+ pre##_eblk(&ctx->ctx, t, t); \
+ BLKC_XLOAD(PRE, t, s); s += PRE##_BLKSZ; \
+ BLKC_STORE(PRE, d, t); d += PRE##_BLKSZ; \
+ plan.from_input -= PRE##_BLKSZ; \
} \
- off = 0; \
- BLKC_STORE(PRE, ctx->iv, iv); \
} \
\
- /* --- Tidying up the tail end --- */ \
- \
- if (sz) { \
- small: \
- do { \
- register octet x = *s++; \
- ctx->iv[off] ^= x; \
- if (d) *d++ = ctx->iv[off]; \
- off++; \
- sz--; \
- } while (sz); \
+ /* Final portion. Note that the buffer must be empty if there is a \
+ * tail, since otherwise the input data would have been part of the \
+ * head portion instad. */ \
+ if (!plan.tail) \
+ BLKC_STORE(PRE, ctx->b, t); \
+ else { \
+ pre##_eblk(&ctx->ctx, t, t); \
+ BLKC_STORE(PRE, ctx->b, t); \
+ p = ctx->b; ctx->off += plan.tail; \
+ if (s) while (plan.tail--) { y = *s++ ^ *p; *p++ = y; if (d) *d++ = y; } \
+ else if (d) { memcpy(d, p, plan.tail); d += plan.tail; } \
} \
- \
- /* --- Done --- */ \
- \
- ctx->off = off; \
- return; \
} \
\
/* --- @pre_cfbdecrypt@ --- * \
*/ \
\
void pre##_cfbdecrypt(pre##_cfbctx *ctx, \
- const void *src, void *dest, \
- size_t sz) \
+ const void *src, void *dest, \
+ size_t sz) \
{ \
+ rsvr_plan plan; \
const octet *s = src; \
- octet *d = dest; \
- unsigned off = ctx->off; \
- \
- /* --- Empty blocks are trivial --- */ \
- \
- if (!sz) \
- return; \
- \
- /* --- If I can deal with the block from my buffer, do that --- */ \
- \
- if (sz < PRE##_BLKSZ - off) \
- goto small; \
- \
- /* --- Finish off what's left in my buffer --- */ \
- \
- while (off < PRE##_BLKSZ) { \
- register octet x = *s++; \
- *d++ = ctx->iv[off] ^ x; \
- ctx->iv[off++] = x; \
- sz--; \
- } \
- \
- /* --- Main encryption loop --- */ \
- \
- { \
- uint32 iv[PRE##_BLKSZ / 4]; \
- BLKC_LOAD(PRE, iv, ctx->iv); \
- \
- for (;;) { \
- uint32 x[PRE##_BLKSZ / 4]; \
- pre##_eblk(&ctx->ctx, iv, iv); \
- if (sz < PRE##_BLKSZ) \
- break; \
- BLKC_LOAD(PRE, x, s); \
- BLKC_XSTORE(PRE, d, iv, x); \
- BLKC_MOVE(PRE, iv, x); \
- s += PRE##_BLKSZ; \
- d += PRE##_BLKSZ; \
- sz -= PRE##_BLKSZ; \
+ octet *d = dest, *p; \
+ uint32 t[PRE##_BLKSZ/4], u[PRE##_BLKSZ/4]; \
+ octet y; \
+ \
+ /* Construct a plan and prepare to follow through. */ \
+ rsvr_mkplan(&plan, &pre##_cfbpolicy, ctx->off, sz); \
+ BLKC_LOAD(PRE, t, ctx->b); \
+ \
+ /* Initial portion, fulfilled from the buffer. If the chunk is small \
+ * enough, then this will be the only portion. If the buffer is \
+ * currently empty, then we must prepare it. \
+ */ \
+ if (plan.head) { \
+ if (!ctx->off) { \
+ pre##_eblk(&ctx->ctx, t, t); \
+ BLKC_STORE(PRE, ctx->b, t); \
} \
- off = 0; \
- BLKC_STORE(PRE, ctx->iv, iv); \
+ p = ctx->b + ctx->off; \
+ ctx->off += plan.head; \
+ while (plan.head--) { y = *s++; *d++ = y ^ *p; *p++ = y; } \
+ BLKC_LOAD(PRE, t, ctx->b); \
} \
\
- /* --- Tidying up the tail end --- */ \
+ /* If the buffer is all used, then reset it ready for next time. */ \
+ ctx->off -= plan.from_rsvr; \
\
- if (sz) { \
- small: \
- do { \
- register octet x = *s++; \
- *d++ = ctx->iv[off] ^ x; \
- ctx->iv[off++] = x; \
- sz--; \
- } while (sz); \
+ /* Handle multiple whole blocks. */ \
+ while (plan.from_input) { \
+ pre##_eblk(&ctx->ctx, t, t); \
+ BLKC_LOAD(PRE, u, s); s += PRE##_BLKSZ; \
+ BLKC_XSTORE(PRE, d, t, u); d += PRE##_BLKSZ; \
+ BLKC_MOVE(PRE, t, u); \
+ plan.from_input -= PRE##_BLKSZ; \
} \
\
- /* --- Done --- */ \
- \
- ctx->off = off; \
- return; \
+ /* Final portion. Note that the buffer must be empty if there is a \
+ * tail, since otherwise the input data would have been part of the \
+ * head portion instad. */ \
+ if (!plan.tail) \
+ BLKC_STORE(PRE, ctx->b, t); \
+ else { \
+ pre##_eblk(&ctx->ctx, t, t); \
+ BLKC_STORE(PRE, ctx->b, t); \
+ p = ctx->b; \
+ ctx->off += plan.tail; \
+ while (plan.tail--) { y = *s++; *d++ = y ^ *p; *p++ = y; } \
+ } \
} \
\
/* --- Generic cipher interface --- */ \
} \
\
static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) \
-{ \
- gctx *g = (gctx *)c; \
- pre##_cfbencrypt(&g->k, s, t, sz); \
-} \
+ { gctx *g = (gctx *)c; pre##_cfbencrypt(&g->k, s, t, sz); } \
\
static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz) \
-{ \
- gctx *g = (gctx *)c; \
- pre##_cfbdecrypt(&g->k, s, t, sz); \
-} \
+ { gctx *g = (gctx *)c; pre##_cfbdecrypt(&g->k, s, t, sz); } \
\
static void gdestroy(gcipher *c) \
-{ \
- gctx *g = (gctx *)c; \
- BURN(*g); \
- S_DESTROY(g); \
-} \
+ { gctx *g = (gctx *)c; BURN(*g); S_DESTROY(g); } \
\
static void gsetiv(gcipher *c, const void *iv) \
-{ \
- gctx *g = (gctx *)c; \
- pre##_cfbsetiv(&g->k, iv); \
-} \
+ { gctx *g = (gctx *)c; pre##_cfbsetiv(&g->k, iv); } \
\
static void gbdry(gcipher *c) \
-{ \
- gctx *g = (gctx *)c; \
- pre##_cfbbdry(&g->k); \
-} \
+ { gctx *g = (gctx *)c; pre##_cfbbdry(&g->k); } \
\
static const gcipher_ops gops = { \
&pre##_cfb, \
#ifdef TEST_RIG
-#include <stdio.h>
-
-#include "daftstory.h"
+#include "modes-test.h"
/* --- @CFB_TEST@ --- *
*
#define CFB_TESTX(PRE, pre, name, fname) \
\
-/* --- Initial plaintext for the test --- */ \
- \
-static const octet text[] = TEXT; \
- \
-/* --- Key and IV to use --- */ \
+static pre##_ctx key; \
+static pre##_cfbctx ctx; \
\
-static const octet key[] = KEY; \
-static const octet iv[] = IV; \
+static void pre##_cfb_test_setup(const octet *k, size_t ksz) \
+ { pre##_init(&key, k, ksz); pre##_cfbsetkey(&ctx, &key); } \
\
-/* --- Buffers for encryption and decryption output --- */ \
+static void pre##_cfb_test_reset(const octet *iv) \
+ { pre##_cfbsetiv(&ctx, iv); } \
\
-static octet ct[sizeof(text)]; \
-static octet pt[sizeof(text)]; \
+static void pre##_cfb_test_enc(const octet *s, octet *d, size_t sz) \
+ { pre##_cfbencrypt(&ctx, s, d, sz); } \
\
-static void hexdump(const octet *p, size_t sz, size_t off) \
-{ \
- const octet *q = p + sz; \
- for (sz = 0; p < q; p++, sz++) { \
- printf("%02x", *p); \
- if ((off + sz + 1) % PRE##_BLKSZ == 0) \
- putchar(':'); \
- } \
-} \
+static void pre##_cfb_test_dec(const octet *s, octet *d, size_t sz) \
+ { pre##_cfbdecrypt(&ctx, s, d, sz); } \
\
-int main(void) \
+int main(int argc, char *argv[]) \
{ \
- size_t sz = 0, rest; \
- pre##_cfbctx ctx; \
- int status = 0; \
- int done = 0; \
- pre##_ctx k; \
- \
- size_t keysz = PRE##_KEYSZ ? \
- PRE##_KEYSZ : strlen((const char *)key); \
- \
- fputs(name "-cfb: ", stdout); \
- \
- pre##_init(&k, key, keysz); \
- pre##_cfbsetkey(&ctx, &k); \
- \
- while (sz <= sizeof(text)) { \
- rest = sizeof(text) - sz; \
- memcpy(ct, text, sizeof(text)); \
- pre##_cfbsetiv(&ctx, iv); \
- pre##_cfbencrypt(&ctx, ct, ct, sz); \
- pre##_cfbencrypt(&ctx, ct + sz, ct + sz, rest); \
- memcpy(pt, ct, sizeof(text)); \
- pre##_cfbsetiv(&ctx, iv); \
- pre##_cfbdecrypt(&ctx, pt, pt, rest); \
- pre##_cfbdecrypt(&ctx, pt + rest, pt + rest, sz); \
- if (memcmp(pt, text, sizeof(text)) == 0) { \
- done++; \
- if (sizeof(text) < 40 || done % 8 == 0) \
- fputc('.', stdout); \
- if (done % 480 == 0) \
- fputs("\n\t", stdout); \
- fflush(stdout); \
- } else { \
- printf("\nError (sz = %lu)\n", (unsigned long)sz); \
- status = 1; \
- printf("\tplaintext = "); hexdump(text, sz, 0); \
- printf(", "); hexdump(text + sz, rest, sz); \
- fputc('\n', stdout); \
- printf("\tciphertext = "); hexdump(ct, sz, 0); \
- printf(", "); hexdump(ct + sz, rest, sz); \
- fputc('\n', stdout); \
- printf("\trecovered text = "); hexdump(pt, sz, 0); \
- printf(", "); hexdump(pt + sz, rest, sz); \
- fputc('\n', stdout); \
- fputc('\n', stdout); \
- } \
- if (sz < 63) \
- sz++; \
- else \
- sz += 9; \
- } \
- \
- fputs(status ? " failed\n" : " ok\n", stdout); \
- return (status); \
+ return test_encmode(fname "-cfb", PRE##_KEYSZ, PRE##_BLKSZ, 1, 0, \
+ pre##_cfb_test_setup, pre##_cfb_test_reset, \
+ pre##_cfb_test_enc, pre##_cfb_test_dec, \
+ argc, argv); \
}
#else
typedef struct pre##_cfbctx { \
pre##_ctx ctx; /* Underlying cipher context */ \
unsigned off; /* Offset into @iv@ buffer */ \
- octet iv[PRE##_BLKSZ]; /* Previous ciphertext or IV */ \
+ octet b[PRE##_BLKSZ]; /* Previous ciphertext or IV */ \
} pre##_cfbctx; \
\
/* --- @pre_cfbgetiv@ --- * \
/// MA 02111-1307, USA.
///--------------------------------------------------------------------------
-/// External definitions.
+/// Preliminaries.
#include "config.h"
#include "asm-common.h"
-///--------------------------------------------------------------------------
-/// Main.code.
-
.arch armv7-a
.fpu neon
+
.text
+///--------------------------------------------------------------------------
+/// Main.code.
+
FUNC(chacha_core_arm_neon)
// Arguments are in registers.
/// MA 02111-1307, USA.
///--------------------------------------------------------------------------
-/// External definitions.
+/// Preliminaries.
#include "config.h"
#include "asm-common.h"
-///--------------------------------------------------------------------------
-/// Main.code.
-
.arch armv8-a
+
.text
+///--------------------------------------------------------------------------
+/// Main.code.
+
FUNC(chacha_core_arm64)
// Arguments are in registers.
--- /dev/null
+/* -*-c-*-
+ *
+ * AEAD schemes based on ChaCha and Poly1305
+ *
+ * (c) 2018 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "chacha.h"
+#include "latinpoly-def.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+LATINPOLY_DEF(chacha20, chacha, "chacha20")
+LATINPOLY_DEF(chacha12, chacha, "chacha12")
+LATINPOLY_DEF(chacha8, chacha, "chacha8")
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <mLib/quis.h>
+#include <mLib/testrig.h>
+#include "latinpoly-test.h"
+
+static int check_chacha20_poly1305(dstr *v)
+ { return latinpoly_test(&chacha20_poly1305, v); }
+static int check_chacha12_poly1305(dstr *v)
+ { return latinpoly_test(&chacha12_poly1305, v); }
+static int check_chacha8_poly1305(dstr *v)
+ { return latinpoly_test(&chacha8_poly1305, v); }
+static int check_chacha20_naclbox(dstr *v)
+ { return latinpoly_test(&chacha20_naclbox, v); }
+static int check_chacha12_naclbox(dstr *v)
+ { return latinpoly_test(&chacha12_naclbox, v); }
+static int check_chacha8_naclbox(dstr *v)
+ { return latinpoly_test(&chacha8_naclbox, v); }
+
+static const test_chunk tests[] = {
+ { "chacha20-poly1305", check_chacha20_poly1305,
+ { &type_hex, &type_hex, &type_hex, &type_hex, &type_hex, &type_hex } },
+ { "chacha12-poly1305", check_chacha12_poly1305,
+ { &type_hex, &type_hex, &type_hex, &type_hex, &type_hex, &type_hex } },
+ { "chacha8-poly1305", check_chacha8_poly1305,
+ { &type_hex, &type_hex, &type_hex, &type_hex, &type_hex, &type_hex } },
+ { "chacha20-naclbox", check_chacha20_naclbox,
+ { &type_hex, &type_hex, &type_hex, &type_hex, &type_hex, &type_hex } },
+ { "chacha12-naclbox", check_chacha12_naclbox,
+ { &type_hex, &type_hex, &type_hex, &type_hex, &type_hex, &type_hex } },
+ { "chacha8-naclbox", check_chacha8_naclbox,
+ { &type_hex, &type_hex, &type_hex, &type_hex, &type_hex, &type_hex } },
+ { 0, 0, { 0 } }
+#undef TEST
+};
+
+int main(int argc, char *argv[])
+{
+ ego(argv[0]);
+ test_run(argc, argv, tests, SRCDIR"/t/chacha");
+ return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
/// MA 02111-1307, USA.
///--------------------------------------------------------------------------
-/// External definitions.
+/// Preliminaries.
#include "config.h"
#include "asm-common.h"
+ .text
+
///--------------------------------------------------------------------------
/// Main code.
- .arch pentium4
- .text
+FUNC(chacha_core_x86ish_avx)
+ .arch .avx
+ vzeroupper
+ endprologue
+ // drop through...
+ENDFUNC
+
+ .arch pentium4
FUNC(chacha_core_x86ish_sse2)
# define SAVE3 [esp]
pushreg ebp
- setfp ebp
+ setfp
sub esp, 16
mov IN, [ebp + 12]
mov OUT, [ebp + 16]
// c += d; b ^= c; b <<<= 7
paddd xmm2, xmm3
- pshufd xmm3, xmm3, SHUF(2, 1, 0, 3)
+ pshufd xmm3, xmm3, SHUF(3, 0, 1, 2)
pxor xmm1, xmm2
- pshufd xmm2, xmm2, SHUF(1, 0, 3, 2)
+ pshufd xmm2, xmm2, SHUF(2, 3, 0, 1)
movdqa xmm4, xmm1
pslld xmm1, 7
psrld xmm4, 25
//
// The shuffles have quite high latency, so they've mostly been
// pushed upwards. The remaining one can't be moved, though.
- pshufd xmm1, xmm1, SHUF(0, 3, 2, 1)
+ pshufd xmm1, xmm1, SHUF(1, 2, 3, 0)
// Apply the diagonal quarterround to each of the columns
// simultaneously.
// c += d; b ^= c; b <<<= 7
paddd xmm2, xmm3
- pshufd xmm3, xmm3, SHUF(0, 3, 2, 1)
+ pshufd xmm3, xmm3, SHUF(1, 2, 3, 0)
pxor xmm1, xmm2
- pshufd xmm2, xmm2, SHUF(1, 0, 3, 2)
+ pshufd xmm2, xmm2, SHUF(2, 3, 0, 1)
movdqa xmm4, xmm1
pslld xmm1, 7
psrld xmm4, 25
// Finally, finish off undoing the transpose, and we're done for this
// doubleround. Again, most of this was done above so we don't have
// to wait for the shuffles.
- pshufd xmm1, xmm1, SHUF(2, 1, 0, 3)
+ pshufd xmm1, xmm1, SHUF(3, 0, 1, 2)
// Decrement the loop counter and see if we should go round again.
sub NR, 2
#include "grand.h"
#include "keysz.h"
#include "paranoia.h"
+#include "rsvr.h"
/*----- Global variables --------------------------------------------------*/
#if CPUFAM_X86 || CPUFAM_AMD64
extern core__functype chacha_core_x86ish_sse2;
+extern core__functype chacha_core_x86ish_avx;
#endif
#if CPUFAM_ARMEL
static core__functype *pick_core(void)
{
#if CPUFAM_X86 || CPUFAM_AMD64
+ DISPATCH_PICK_COND(chacha_core, chacha_core_x86ish_avx,
+ cpu_feature_p(CPUFEAT_X86_AVX));
DISPATCH_PICK_COND(chacha_core, chacha_core_x86ish_sse2,
cpu_feature_p(CPUFEAT_X86_SSE2));
#endif
/*----- ChaCha implementation ---------------------------------------------*/
+static const octet zerononce[XCHACHA_NONCESZ];
+
/* --- @chacha_init@ --- *
*
* Arguments: @chacha_ctx *ctx@ = context to fill in
void chacha_init(chacha_ctx *ctx, const void *key, size_t ksz,
const void *nonce)
{
- static const octet zerononce[CHACHA_NONCESZ];
-
populate(ctx->a, key, ksz);
chacha_setnonce(ctx, nonce ? nonce : zerononce);
}
void chacha_seeku64(chacha_ctx *ctx, kludge64 i)
{
ctx->a[12] = LO64(i); ctx->a[13] = HI64(i);
- ctx->bufi = CHACHA_OUTSZ;
+ ctx->off = CHACHA_OUTSZ;
}
void chacha_seek_ietf(chacha_ctx *ctx, uint32 i)
* to @dest@.
*/
+static const rsvr_policy policy = { 0, CHACHA_OUTSZ, CHACHA_OUTSZ };
+
#define CHACHA_ENCRYPT(r, ctx, src, dest, sz) \
chacha##r##_encrypt(ctx, src, dest, sz)
#define DEFENCRYPT(r) \
chacha_matrix b; \
const octet *s = src; \
octet *d = dest; \
- size_t n; \
+ rsvr_plan plan; \
kludge64 pos, delta; \
\
- SALSA20_OUTBUF(ctx, d, s, sz); \
- if (!sz) return; \
- \
- if (!dest) { \
- n = sz/CHACHA_OUTSZ; \
- pos = chacha_tellu64(ctx); \
- ASSIGN64(delta, n); \
- ADD64(pos, pos, delta); \
- chacha_seeku64(ctx, pos); \
- sz = sz%CHACHA_OUTSZ; \
- } else if (!src) { \
- while (sz >= CHACHA_OUTSZ) { \
- core(r, ctx->a, b); \
- CHACHA_STEP(ctx->a); \
- SALSA20_GENFULL(b, d); \
- sz -= CHACHA_OUTSZ; \
+ rsvr_mkplan(&plan, &policy, ctx->off, sz); \
+ \
+ if (plan.head) { \
+ if (!ctx->off) { \
+ core(r, ctx->a, b); CHACHA_STEP(ctx->a); \
+ SALSA20_PREPBUF(ctx, b); \
} \
- } else { \
- while (sz >= CHACHA_OUTSZ) { \
- core(r, ctx->a, b); \
- CHACHA_STEP(ctx->a); \
- SALSA20_MIXFULL(b, d, s); \
- sz -= CHACHA_OUTSZ; \
+ SALSA20_OUTBUF(ctx, d, s, plan.head); \
+ } \
+ \
+ ctx->off -= plan.from_rsvr; \
+ \
+ if (!d) { \
+ if (plan.from_input) { \
+ pos = chacha_tellu64(ctx); \
+ ASSIGN64(delta, plan.from_input/SALSA20_OUTSZ); \
+ ADD64(pos, pos, delta); \
+ chacha_seeku64(ctx, pos); \
} \
+ } else if (!s) while (plan.from_input) { \
+ core(r, ctx->a, b); CHACHA_STEP(ctx->a); \
+ SALSA20_GENFULL(b, d); plan.from_input -= CHACHA_OUTSZ; \
+ } else while (plan.from_input) { \
+ core(r, ctx->a, b); CHACHA_STEP(ctx->a); \
+ SALSA20_MIXFULL(b, d, s); plan.from_input -= CHACHA_OUTSZ; \
} \
\
- if (sz) { \
- core(r, ctx->a, b); \
- CHACHA_STEP(ctx->a); \
+ if (plan.tail) { \
+ core(r, ctx->a, b); CHACHA_STEP(ctx->a); \
SALSA20_PREPBUF(ctx, b); \
- SALSA20_OUTBUF(ctx, d, s, sz); \
- assert(!sz); \
+ SALSA20_OUTBUF(ctx, d, s, plan.tail); \
} \
}
CHACHA_VARS(DEFENCRYPT)
void XCHACHA_INIT(r, XCHACHA_CTX(r) *ctx, \
const void *key, size_t ksz, const void *nonce) \
{ \
- static const octet zerononce[XCHACHA_NONCESZ]; \
- \
populate(ctx->k, key, ksz); \
ctx->s.a[ 0] = CHACHA_A256; \
ctx->s.a[ 1] = CHACHA_B256; \
typedef struct chacha_ctx {
chacha_matrix a;
- octet buf[CHACHA_OUTSZ];
- size_t bufi;
+ octet b[CHACHA_OUTSZ];
+ unsigned off;
} chacha_ctx;
#define XCHACHA_DEFCTX(name) \
*/
extern void chacha_init(chacha_ctx */*ctx*/,
- const void */*key*/, size_t /*ksz*/,
- const void */*nonce*/);
+ const void */*key*/, size_t /*ksz*/,
+ const void */*nonce*/);
/* --- @chacha_setnonce{,_ietf}@ --- *
*
--- /dev/null
+/* -*-c-*-
+ *
+ * The CMAC message-authentication code
+ *
+ * (c) 2017 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef CATACOMB_CMAC_DEF_H
+#define CATACOMB_CMAC_DEF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#ifndef CATACOMB_ARENA_H
+# include "arena.h"
+#endif
+
+#ifndef CATACOMB_BLKC_H
+# include "blkc.h"
+#endif
+
+#ifndef CATACOMB_GMAC_H
+# include "gmac.h"
+#endif
+
+#ifndef CATACOMB_PARANOIA_H
+# include "paranoia.h"
+#endif
+
+#ifndef CATACOMB_RSVR_H
+# include "rsvr.h"
+#endif
+
+/*----- Low-level OMAC definitions ----------------------------------------*/
+
+/* --- @OMAC_BLOCK@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
+ * @pre_ctx *k@ = pointer to expanded blockcipher key
+ * @uint32 *a@ = accumulator state to update
+ * @octet *p@ = pointer to input block to accumulate
+ *
+ * Use: Update the state @a@ from the input block @p@.
+ */
+
+#define OMAC_BLOCK(PRE, pre, k, a, p) do { \
+ pre##_ctx *_k = (k); uint32 *_a = (a); const octet *_pp = (p); \
+ BLKC_XLOAD(PRE, _a, _pp); pre##_eblk(_k, _a, _a); \
+} while (0)
+
+/* --- @OMAC_DEF@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Creates low-level implementation for the OMAC message-
+ * authentication mode.
+ */
+
+#define OMAC_DEF(PRE, pre) \
+ \
+/* Buffering policy for OMAC. */ \
+const rsvr_policy pre##_omacpolicy = \
+ { RSVRF_FULL, PRE##_BLKSZ, PRE##_BLKSZ }; \
+ \
+/* --- @pre_omacmasks@ --- * \
+ * \
+ * Arguments: @pre_ctx *k@ = pointer to expanded blockcipher key \
+ * @uint32 *m0, *m1@ = buffers to store the masks \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initialize the OMAC masks. The mask buffers are \
+ * @PRE_BLKSZ/4@ words long. The mmask @m0@ is applied to \
+ * messages which are a whole number of blocks long; @m1@ \
+ * is applied to messages with an incomplete final block, \
+ * following the 10* padding. \
+ */ \
+ \
+void pre##_omacmasks(pre##_ctx *k, uint32 *m0, uint32 *m1) \
+{ \
+ uint32 t[PRE##_BLKSZ/4]; \
+ \
+ BLKC_ZERO(PRE, t); pre##_eblk(k, t, t); \
+ BLKC_BLSHIFT(PRE, IRRED, m0, t); \
+ BLKC_BLSHIFT(PRE, IRRED, m1, m0); \
+} \
+ \
+/* --- @pre_omacdone@ --- * \
+ * \
+ * Arguments: @pre_ctx *k@ = pointer to expanded blockcipher key \
+ * @const uint32 *m0, *m1@ = masks \
+ * @uint32 *a@ = accumulator state to update \
+ * @octet *p@ = pointer to input buffer (clobbered) \
+ * @unsigned n@ = size of input buffer (no more than \
+ * @PRE_BLKSZ@) \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Update and finalize the OMAC hash state with the last \
+ * few bytes of input. The final tag is left in @a@. \
+ */ \
+ \
+void pre##_omacdone(pre##_ctx *k, const uint32 *m0, const uint32 *m1, \
+ uint32 *a, octet *p, unsigned n) \
+{ \
+ /* Do any necessary padding and apply the appropriate mask to the \
+ * accumulator. \
+ */ \
+ if (n == PRE##_BLKSZ) \
+ BLKC_XMOVE(PRE, a, m0); \
+ else { \
+ p[n] = 0x80; memset(p + n + 1, 0, PRE##_BLKSZ - n - 1); \
+ BLKC_XMOVE(PRE, a, m1); \
+ } \
+ \
+ /* Fetch the buffer contents and cycle the block cipher one last \
+ * time. \
+ */ \
+ BLKC_XLOAD(PRE, a, p); \
+ pre##_eblk(k, a, a); \
+}
+
+/*----- Properly cooked CMAC ----------------------------------------------*/
+
+/* --- @CMAC_DEF@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Creates an implementation for the CMAC message-authentication
+ * mode.
+ */
+
+#define CMAC_DEF(PRE, pre) CMAC_DEFX(PRE, pre, #pre, #pre)
+
+#define CMAC_DEFX(PRE, pre, name, fname) \
+ \
+OMAC_DEF(PRE, pre) \
+ \
+/* --- @pre_cmacsetkey@ --- * \
+ * \
+ * Arguments: @pre_cmackey *key@ = pointer to CMAC key block \
+ * @ocnst void *k@ = pointer to key material \
+ * @size_t ksz@ = size of key material \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes a CMAC key. This can be used for several \
+ * MAC operations. \
+ */ \
+ \
+void pre##_cmacsetkey(pre##_cmackey *key, const void *k, size_t ksz) \
+{ \
+ pre##_init(&key->ctx, k, ksz); \
+ pre##_omacmasks(&key->ctx, key->m0, key->m1); \
+} \
+ \
+/* --- @pre##_cmacinit@ --- * \
+ * \
+ * Arguments: @pre_cmacctx *ctx@ = pointer to context block \
+ * @pre_cmackey *k@ = key block \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes a CMAC context ready to process a message. \
+ * It's not necessary to keep the key around. \
+ */ \
+ \
+void pre##_cmacinit(pre##_cmacctx *ctx, const pre##_cmackey *k) \
+ { ctx->k = *k; ctx->off = 0; BLKC_ZERO(PRE, ctx->a); } \
+ \
+/* --- @pre_cmachash@ --- * \
+ * \
+ * Arguments: @pre_cmacctx *ctx@ = pointer to CMAC context block \
+ * @ocnst void *p@ = pointer to message buffer \
+ * @size_t sz@ = size of message buffer \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Hashes some input data. \
+ */ \
+ \
+void pre##_cmachash(pre##_cmacctx *ctx, const void *p, size_t sz) \
+{ \
+ rsvr_state st; \
+ const octet *q; \
+ \
+ rsvr_setup(&st, &pre##_omacpolicy, ctx->b, &ctx->off, p, sz); \
+ RSVR_DO(&st) while ((q = RSVR_NEXT(&st, PRE##_BLKSZ)) != 0) \
+ OMAC_BLOCK(PRE, pre, &ctx->k.ctx, ctx->a, q); \
+} \
+ \
+/* --- @pre_cmacdone@ --- * \
+ * \
+ * Arguments: @pre_cmacctx *ctx@ = pointer to CMAC context block \
+ * @void *t@ = where to write the tag \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Finishes a MAC operation and produces the tag. The \
+ * context is clobbered and can't be used for anything \
+ * useful any more. \
+ */ \
+ \
+void pre##_cmacdone(pre##_cmacctx *ctx, void *t) \
+{ \
+ pre##_omacdone(&ctx->k.ctx, ctx->k.m0, ctx->k.m1, \
+ ctx->a, ctx->b, ctx->off); \
+ BLKC_STORE(PRE, t, ctx->a); \
+} \
+ \
+/* --- Generic MAC interface --- */ \
+ \
+static const gmac_ops gkops; \
+static const ghash_ops gops; \
+ \
+typedef struct gkctx { \
+ gmac m; \
+ pre##_cmackey k; \
+} gkctx; \
+ \
+typedef struct gctx { \
+ ghash h; \
+ pre##_cmacctx c; \
+ octet buf[PRE##_BLKSZ]; \
+} gctx; \
+ \
+static ghash *gkinit(gmac *m) \
+{ \
+ gkctx *gk = (gkctx *)m; \
+ gctx *g = S_CREATE(gctx); \
+ g->h.ops = &gops; \
+ pre##_cmacinit(&g->c, &gk->k); \
+ return (&g->h); \
+} \
+ \
+static gmac *gkey(const void *k, size_t sz) \
+{ \
+ gkctx *gk = S_CREATE(gkctx); \
+ gk->m.ops = &gkops; \
+ pre##_cmacsetkey(&gk->k, k, sz); \
+ return (&gk->m); \
+} \
+ \
+static void ghhash(ghash *h, const void *p, size_t sz) \
+ { gctx *g = (gctx *)h; pre##_cmachash(&g->c, p, sz); } \
+ \
+static octet *ghdone(ghash *h, void *buf) \
+{ \
+ gctx *g = (gctx *)h; \
+ if (!buf) buf = g->buf; \
+ pre##_cmacdone(&g->c, buf); \
+ return (buf); \
+} \
+ \
+static ghash *ghcopy(ghash *h) \
+{ \
+ gctx *g = (gctx *)h; \
+ gctx *gg = S_CREATE(gctx); \
+ memcpy(gg, g, sizeof(gctx)); \
+ return (&gg->h); \
+} \
+ \
+static void ghdestroy(ghash *h) \
+ { gctx *g = (gctx *)h; BURN(*g); S_DESTROY(g); } \
+ \
+static void gkdestroy(gmac *m) \
+ { gkctx *gk = (gkctx *)m; BURN(*gk); S_DESTROY(gk); } \
+ \
+static ghash *ghinit(void) \
+{ \
+ assert(((void)"Attempt to instantiate an unkeyed MAC", 0)); \
+ return (0); \
+} \
+ \
+const gcmac pre##_cmac = \
+ { name "-cmac", PRE##_BLKSZ, pre##_keysz, gkey }; \
+static const gmac_ops gkops = { &pre##_cmac, gkinit, gkdestroy }; \
+static const gchash gch = { name "-cmac", PRE##_BLKSZ, ghinit }; \
+static const ghash_ops gops = \
+ { &gch, ghhash, ghdone, ghdestroy, ghcopy }; \
+ \
+CMAC_TESTX(PRE, pre, name, fname)
+
+#define CMAC_TEST(PRE, pre) HMAC_TESTX(PRE, pre, #pre, #pre)
+
+/* --- @CMAC_TEST@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Standard test rig for CMAC functions.
+ */
+
+#ifdef TEST_RIG
+
+#include <stdio.h>
+
+#include <mLib/dstr.h>
+#include <mLib/quis.h>
+#include <mLib/testrig.h>
+
+#define CMAC_TESTX(PRE, pre, name, fname) \
+ \
+static int macverify(dstr *v) \
+{ \
+ pre##_cmacctx cctx; \
+ pre##_cmackey ckey; \
+ int ok = 1; \
+ int i; \
+ octet *p; \
+ int szs[] = { 1, 7, 192, -1, 0 }, *ip; \
+ size_t csz; \
+ dstr d; \
+ \
+ dstr_create(&d); \
+ dstr_ensure(&d, PRE##_BLKSZ); \
+ d.len = PRE##_BLKSZ; \
+ \
+ pre##_cmacsetkey(&ckey, v[0].buf, v[0].len); \
+ \
+ for (ip = szs; *ip; ip++) { \
+ i = *ip; \
+ csz = v[1].len; \
+ if (i == -1) \
+ i = csz; \
+ if (i > csz) \
+ continue; \
+ p = (octet *)v[1].buf; \
+ pre##_cmacinit(&cctx, &ckey); \
+ while (csz) { \
+ if (i > csz) \
+ i = csz; \
+ pre##_cmachash(&cctx, p, i); \
+ p += i; \
+ csz -= i; \
+ } \
+ pre##_cmacdone(&cctx, d.buf); \
+ if (memcmp(d.buf, v[2].buf, PRE##_BLKSZ) != 0) { \
+ printf("\nfail:\n\tstep = %i\n\tkey = ", *ip); \
+ type_hex.dump(&v[0], stdout); \
+ fputs("\n\tinput = ", stdout); \
+ type_hex.dump(&v[1], stdout); \
+ fputs("\n\texpected = ", stdout); \
+ type_hex.dump(&v[2], stdout); \
+ fputs("\n\tcomputed = ", stdout); \
+ type_hex.dump(&d, stdout); \
+ putchar('\n'); \
+ ok = 0; \
+ } \
+ } \
+ \
+ dstr_destroy(&d); \
+ return (ok); \
+} \
+ \
+static test_chunk macdefs[] = { \
+ { name "-cmac", macverify, \
+ { &type_hex, &type_hex, &type_hex, 0 } }, \
+ { 0, 0, { 0 } } \
+}; \
+ \
+int main(int argc, char *argv[]) \
+{ \
+ ego(argv[0]); \
+ test_run(argc, argv, macdefs, SRCDIR"/t/" fname); \
+ return (0); \
+}
+
+#else
+# define CMAC_TESTX(PRE, pre, name, fname)
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
--- /dev/null
+/* -*-c-*-
+ *
+ * The CMAC message-authentication code
+ *
+ * (c) 2017 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Notes on CMAC -----------------------------------------------------*
+ *
+ * CMAC was designed in 2003 by Tetsu Iwata and Kaoru Kurosawa as a reliable
+ * general purpose message-authentication code based on CBC-MAC. CBC-MAC's
+ * deficiencies have been well known since at least 2000 when Bellare,
+ * Kilian, and Rogaway proved its security on constant-length messages.
+ * Black and Rogaway in 2000 described a number of three-key constructions
+ * for extending CBC-MAC's domain securely to arbitrary strings, culminating
+ * in a mode they named `XCBC', which uses a blockcipher key and two XOR
+ * masks. Iwata and Kurosawa's original proposal, named `OMAC', refined XCBC
+ * by deriving the masks from the key, producing a `one-key MAC'. Bellare,
+ * Rogaway, and Wagner slightly simplified the way the masks were derived
+ * when they used OMAC as a part of their EAX authenticated-encryption mode,
+ * and this change was adopted by NIST when they standardized OMAC, under the
+ * name `CMAC', in SP800-38B.
+ *
+ * NIST specify CMAC only for 64- and 128-bit blockciphers. This
+ * implementation extends it to other lengths in the obvious way.
+ */
+
+#ifndef CATACOMB_CMAC_H
+#define CATACOMB_CMAC_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GMAC_H
+# include "gmac.h"
+#endif
+
+#ifndef CATACOMB_RSVR_H
+# include "rsvr.h"
+#endif
+
+/*----- Low-level OMAC declarations ---------------------------------------*/
+
+/* --- @OMAC_DECL@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Defines low-level implementation for the OMAC message-
+ * authentication mode.
+ */
+
+#define OMAC_DECL(PRE, pre) \
+ \
+/* Buffering policy for OMAC. */ \
+extern const rsvr_policy pre##_omacpolicy; \
+ \
+/* --- @pre_omacmasks@ --- * \
+ * \
+ * Arguments: @pre_ctx *k@ = pointer to expanded blockcipher key \
+ * @uint32 *m0, *m1@ = buffers to store the masks \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initialize the OMAC masks. The mask buffers are \
+ * @PRE_BLKSZ/4@ words long. The mmask @m0@ is applied to \
+ * messages which are a whole number of blocks long; @m1@ \
+ * is applied to messages with an incomplete final block, \
+ * following the 10* padding. \
+ */ \
+ \
+extern void pre##_omacmasks(pre##_ctx */*k*/, \
+ uint32 */*m0*/, uint32 */*m1*/); \
+ \
+/* --- @pre_omacdone@ --- * \
+ * \
+ * Arguments: @pre_ctx *k@ = pointer to expanded blockcipher key \
+ * @const uint32 *m0, *m1@ = masks \
+ * @uint32 *a@ = accumulator state to update \
+ * @octet *p@ = pointer to input buffer (clobbered) \
+ * @unsigned n@ = size of input buffer (no more than \
+ * @PRE_BLKSZ@) \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Update and finalize the OMAC hash state with the last \
+ * few bytes of input. The final tag is left in @a@. \
+ */ \
+ \
+extern void pre##_omacdone(pre##_ctx */*k*/, \
+ const uint32 */*m0*/, const uint32 */*m1*/, \
+ uint32 */*a*/, octet */*p*/, unsigned /*n*/);
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @CMAC_DECL@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Creates declarations for CMAC message-authentication mode.
+ */
+
+#define CMAC_DECL(PRE, pre) \
+ \
+OMAC_DECL(PRE, pre) \
+ \
+typedef struct pre##_cmackey { \
+ pre##_ctx ctx; /* Underlying cipher context */ \
+ uint32 m0[PRE##_BLKSZ/4], m1[PRE##_BLKSZ/4]; /* Final block masks */ \
+} pre##_cmackey; \
+ \
+typedef struct pre##_cmacctx { \
+ pre##_cmackey k; /* Processed key material */ \
+ uint32 a[PRE##_BLKSZ/4]; /* Chaining state */ \
+ octet b[PRE##_BLKSZ]; /* Input buffer */ \
+ unsigned off; /* Offset into buffered data */ \
+} pre##_cmacctx; \
+ \
+/* --- @pre_cmacsetkey@ --- * \
+ * \
+ * Arguments: @pre_cmackey *key@ = pointer to CMAC key block \
+ * @ocnst void *k@ = pointer to key material \
+ * @size_t ksz@ = size of key material \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes a CMAC key. This can be used for several \
+ * MAC operations. \
+ */ \
+ \
+extern void pre##_cmacsetkey(pre##_cmackey */*key*/, \
+ const void */*k*/, size_t /*ksz*/); \
+ \
+/* --- @pre##_cmacinit@ --- * \
+ * \
+ * Arguments: @pre_cmacctx *ctx@ = pointer to context block \
+ * @pre_cmackey *k@ = key block \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes a CMAC context ready to process a message. \
+ * It's not necessary to keep the key around. \
+ */ \
+ \
+extern void pre##_cmacinit(pre##_cmacctx */*ctx*/, \
+ const pre##_cmackey */*k*/); \
+ \
+/* --- @pre_cmachash@ --- * \
+ * \
+ * Arguments: @pre_cmacctx *ctx@ = pointer to CMAC context block \
+ * @ocnst void *p@ = pointer to message buffer \
+ * @size_t sz@ = size of message buffer \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Hashes some input data. \
+ */ \
+ \
+extern void pre##_cmachash(pre##_cmacctx */*ctx*/, \
+ const void */*p*/, size_t /*sz*/); \
+ \
+/* --- @pre_cmacdone@ --- * \
+ * \
+ * Arguments: @pre_cmacctx *ctx@ = pointer to CMAC context block \
+ * @void *t@ = where to write the tag \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Finishes a MAC operation and produces the tag. \
+ */ \
+ \
+extern void pre##_cmacdone(pre##_cmacctx */*ctx*/, void */*t*/); \
+ \
+/* --- Generic MAC interface --- */ \
+ \
+extern const gcmac pre##_cmac;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
# include "paranoia.h"
#endif
+#ifndef CATACOMB_RSVR_H
+# include "rsvr.h"
+#endif
+
/*----- Macros ------------------------------------------------------------*/
/* --- @COUNTER_DEF@ --- *
*/ \
\
void pre##_countergetiv(const pre##_counterctx *ctx, void *iv) \
-{ \
- BLKC_STORE(PRE, iv, ctx->n); \
-} \
+ { BLKC_STORE(PRE, iv, ctx->c); } \
\
/* --- @pre_countersetiv@ --- * \
* \
*/ \
\
void pre##_countersetiv(pre##_counterctx *ctx, const void *iv) \
-{ \
- BLKC_LOAD(PRE, ctx->n, iv); \
- ctx->off = PRE##_BLKSZ; \
-} \
+ { BLKC_LOAD(PRE, ctx->c, iv); ctx->off = PRE##_BLKSZ; } \
\
/* --- @pre_counterbdry@ --- * \
* \
*/ \
\
void pre##_counterbdry(pre##_counterctx *ctx) \
-{ \
- BLKC_STEP(PRE, ctx->n); \
- ctx->off = PRE##_BLKSZ; \
-} \
+ { BLKC_STEP(PRE, ctx->c); ctx->off = PRE##_BLKSZ; } \
\
/* --- @pre_countersetkey@ --- * \
* \
*/ \
\
void pre##_countersetkey(pre##_counterctx *ctx, const pre##_ctx *k) \
-{ \
- ctx->ctx = *k; \
-} \
+ { ctx->ctx = *k; } \
\
/* --- @pre_counterinit@ --- * \
* \
const void *iv) \
{ \
static const octet zero[PRE##_BLKSZ] = { 0 }; \
+ \
pre##_init(&ctx->ctx, key, sz); \
pre##_countersetiv(ctx, iv ? iv : zero); \
} \
* use the cipher as a random data generator. \
*/ \
\
+static const rsvr_policy pre##_counterpolicy = \
+ { 0, PRE##_BLKSZ, PRE##_BLKSZ }; \
+ \
void pre##_counterencrypt(pre##_counterctx *ctx, \
const void *src, void *dest, \
size_t sz) \
{ \
- const octet *s = src; \
+ rsvr_plan plan; \
+ const octet *s = src, *p; \
octet *d = dest; \
- unsigned off = ctx->off; \
- \
- /* --- Empty blocks are trivial --- */ \
- \
- if (!sz) \
- return; \
- \
- /* --- If I can deal with the block from my buffer, do that --- */ \
- \
- if (sz < PRE##_BLKSZ - off) \
- goto small; \
- \
- /* --- Finish off what's left in my buffer --- */ \
- \
- if (!d) \
- sz -= PRE##_BLKSZ - off; \
- else { \
- while (off < PRE##_BLKSZ) { \
- register octet x = s ? *s++ : 0; \
- *d++ = ctx->buf[off++] ^ x; \
- sz--; \
+ uint32 t[PRE##_BLKSZ/4]; \
+ \
+ /* Construct a plan and prepare to follow through. */ \
+ rsvr_mkplan(&plan, &pre##_counterpolicy, ctx->off, sz); \
+ \
+ /* Initial portion, fulfilled from the buffer. If the chunk is small \
+ * enough, then this will be the only portion. If the buffer is \
+ * currently empty, then we must prepare it. \
+ */ \
+ if (plan.head) { \
+ if (!ctx->off) { \
+ pre##_eblk(&ctx->ctx, ctx->c, t); BLKC_STEP(PRE, ctx->c); \
+ BLKC_STORE(PRE, ctx->b, t); \
} \
+ p = ctx->b + ctx->off; ctx->off += plan.head; \
+ if (!d) /* nothing to do */; \
+ else if (!s) { memcpy(d, p, plan.head); d += plan.head; } \
+ else while (plan.head--) *d++ = *s++ ^ *p++; \
} \
\
- /* --- Main encryption loop --- */ \
- \
- { \
- uint32 n[PRE##_BLKSZ / 4]; \
- \
- for (;;) { \
- pre##_eblk(&ctx->ctx, ctx->n, n); \
- BLKC_STEP(PRE, ctx->n); \
- if (sz < PRE##_BLKSZ) \
- break; \
- if (d) { \
- if (!s) \
- BLKC_STORE(PRE, d, n); \
- else { \
- uint32 x[PRE##_BLKSZ / 4]; \
- BLKC_LOAD(PRE, x, s); \
- BLKC_XSTORE(PRE, d, n, x); \
- s += PRE##_BLKSZ; \
- } \
- d += PRE##_BLKSZ; \
- } \
- sz -= PRE##_BLKSZ; \
- } \
+ /* If the buffer is all used, then reset it ready for next time. */ \
+ ctx->off -= plan.from_rsvr; \
\
- BLKC_STORE(PRE, ctx->buf, n); \
- off = 0; \
+ /* Handle multiple whole blocks. */ \
+ if (!d) \
+ BLKC_ADD(PRE, ctx->c, plan.from_input/PRE##_BLKSZ); \
+ else if (!s) while (plan.from_input) { \
+ pre##_eblk(&ctx->ctx, ctx->c, t); BLKC_STEP(PRE, ctx->c); \
+ BLKC_STORE(PRE, d, t); d += PRE##_BLKSZ; \
+ plan.from_input -= PRE##_BLKSZ; \
+ } else while (plan.from_input) { \
+ pre##_eblk(&ctx->ctx, ctx->c, t); BLKC_STEP(PRE, ctx->c); \
+ BLKC_XLOAD(PRE, t, s); s += PRE##_BLKSZ; \
+ BLKC_STORE(PRE, d, t); d += PRE##_BLKSZ; \
+ plan.from_input -= PRE##_BLKSZ; \
} \
\
- /* --- Tidying up the tail end --- */ \
- \
- if (sz) { \
- small: \
- if (!d) \
- off += sz; \
- else do { \
- register octet x = s ? *s++ : 0; \
- *d++ = ctx->buf[off++] ^ x; \
- sz--; \
- } while (sz); \
+ /* Final portion. Note that the buffer must be empty if there is a \
+ * tail, since otherwise the input data would have been part of the \
+ * head portion instad. */ \
+ if (!plan.tail) \
+ BLKC_STORE(PRE, ctx->b, t); \
+ else { \
+ pre##_eblk(&ctx->ctx, ctx->c, t); BLKC_STEP(PRE, ctx->c); \
+ BLKC_STORE(PRE, ctx->b, t); \
+ p = ctx->b; ctx->off += plan.tail; \
+ if (!d) /* nothing to do */; \
+ else if (!s) { memcpy(d, p, plan.tail); d += plan.tail; } \
+ else while (plan.tail--) *d++ = *s++ ^ *p++; \
} \
- \
- /* --- Done --- */ \
- \
- ctx->off = off; \
- return; \
} \
\
/* --- Generic cipher interface --- */ \
} \
\
static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) \
-{ \
- gctx *g = (gctx *)c; \
- pre##_counterencrypt(&g->k, s, t, sz); \
-} \
+ { gctx *g = (gctx *)c; pre##_counterencrypt(&g->k, s, t, sz); } \
\
static void gdestroy(gcipher *c) \
-{ \
- gctx *g = (gctx *)c; \
- BURN(*g); \
- S_DESTROY(g); \
-} \
+ { gctx *g = (gctx *)c; BURN(*g); S_DESTROY(g); } \
\
static void gsetiv(gcipher *c, const void *iv) \
-{ \
- gctx *g = (gctx *)c; \
- pre##_countersetiv(&g->k, iv); \
-} \
+ { gctx *g = (gctx *)c; pre##_countersetiv(&g->k, iv); } \
\
static void gbdry(gcipher *c) \
-{ \
- gctx *g = (gctx *)c; \
- pre##_counterbdry(&g->k); \
-} \
+ { gctx *g = (gctx *)c; pre##_counterbdry(&g->k); } \
\
static const gcipher_ops gops = { \
&pre##_counter, \
} \
break; \
case GRAND_SEEDINT: \
- BLKC_SET(PRE, g->k.n, va_arg(ap, unsigned)); \
+ BLKC_SET(PRE, g->k.c, va_arg(ap, unsigned)); \
g->k.off = PRE##_BLKSZ; \
break; \
case GRAND_SEEDUINT32: \
- BLKC_SET(PRE, g->k.n, va_arg(ap, uint32)); \
+ BLKC_SET(PRE, g->k.c, va_arg(ap, uint32)); \
g->k.off = PRE##_BLKSZ; \
break; \
case GRAND_SEEDBLOCK: { \
} \
\
static void grfill(grand *r, void *p, size_t sz) \
-{ \
- grctx *g = (grctx *)r; \
- pre##_counterencrypt(&g->k, 0, p, sz); \
-} \
+ { grctx *g = (grctx *)r; pre##_counterencrypt(&g->k, 0, p, sz); } \
\
static const grand_ops grops = { \
name "-counter", \
#ifdef TEST_RIG
-#include <stdio.h>
-
-#include "daftstory.h"
+#include "modes-test.h"
/* --- @COUNTER_TEST@ --- *
*
#define COUNTER_TESTX(PRE, pre, name, fname) \
\
-/* --- Initial plaintext for the test --- */ \
- \
-static const octet text[] = TEXT; \
- \
-/* --- Key and IV to use --- */ \
- \
-static const octet key[] = KEY; \
-static const octet iv[] = IV; \
+static pre##_ctx key; \
+static pre##_counterctx ctx; \
\
-/* --- Buffers for encryption and decryption output --- */ \
+static void pre##_counter_test_setup(const octet *k, size_t ksz) \
+ { pre##_init(&key, k, ksz); pre##_countersetkey(&ctx, &key); } \
\
-static octet ct[sizeof(text)]; \
-static octet pt[sizeof(text)]; \
+static void pre##_counter_test_reset(const octet *iv) \
+ { pre##_countersetiv(&ctx, iv); } \
\
-static void hexdump(const octet *p, size_t sz, size_t off) \
-{ \
- const octet *q = p + sz; \
- for (sz = 0; p < q; p++, sz++) { \
- printf("%02x", *p); \
- if ((off + sz + 1) % PRE##_BLKSZ == 0) \
- putchar(':'); \
- } \
-} \
+static void pre##_counter_test_enc(const octet *s, octet *d, size_t sz) \
+ { pre##_counterencrypt(&ctx, s, d, sz); } \
\
-int main(void) \
+int main(int argc, char *argv[]) \
{ \
- size_t sz = 0, rest; \
- pre##_counterctx ctx; \
- int status = 0; \
- int done = 0; \
- pre##_ctx k; \
- \
- size_t keysz = PRE##_KEYSZ ? \
- PRE##_KEYSZ : strlen((const char *)key); \
- \
- fputs(name "-counter: ", stdout); \
- \
- pre##_init(&k, key, keysz); \
- pre##_countersetkey(&ctx, &k); \
- \
- while (sz <= sizeof(text)) { \
- rest = sizeof(text) - sz; \
- memcpy(ct, text, sizeof(text)); \
- pre##_countersetiv(&ctx, iv); \
- pre##_counterencrypt(&ctx, ct, ct, sz); \
- pre##_counterencrypt(&ctx, ct + sz, ct + sz, rest); \
- memcpy(pt, ct, sizeof(text)); \
- pre##_countersetiv(&ctx, iv); \
- pre##_counterencrypt(&ctx, pt, pt, rest); \
- pre##_counterencrypt(&ctx, pt + rest, pt + rest, sz); \
- if (memcmp(pt, text, sizeof(text)) == 0) { \
- done++; \
- if (sizeof(text) < 40 || done % 8 == 0) \
- fputc('.', stdout); \
- if (done % 480 == 0) \
- fputs("\n\t", stdout); \
- fflush(stdout); \
- } else { \
- printf("\nError (sz = %lu)\n", (unsigned long)sz); \
- status = 1; \
- printf("\tplaintext = "); hexdump(text, sz, 0); \
- printf(", "); hexdump(text + sz, rest, sz); \
- fputc('\n', stdout); \
- printf("\tciphertext = "); hexdump(ct, sz, 0); \
- printf(", "); hexdump(ct + sz, rest, sz); \
- fputc('\n', stdout); \
- printf("\trecovered text = "); hexdump(pt, sz, 0); \
- printf(", "); hexdump(pt + sz, rest, sz); \
- fputc('\n', stdout); \
- fputc('\n', stdout); \
- } \
- if (sz < 63) \
- sz++; \
- else \
- sz += 9; \
- } \
- \
- fputs(status ? " failed\n" : " ok\n", stdout); \
- return (status); \
+ return test_encmode(fname "-counter", PRE##_KEYSZ, PRE##_BLKSZ, 1, 0, \
+ pre##_counter_test_setup, pre##_counter_test_reset, \
+ pre##_counter_test_enc, pre##_counter_test_enc, \
+ argc, argv); \
}
#else
typedef struct pre##_counterctx { \
pre##_ctx ctx; /* Underlying cipher context */ \
unsigned off; /* Current offset in buffer */ \
- octet buf[PRE##_BLKSZ]; /* Output buffer */ \
- uint32 n[PRE##_BLKSZ / 4]; /* Counter */ \
+ octet b[PRE##_BLKSZ]; /* Output buffer */ \
+ uint32 c[PRE##_BLKSZ / 4]; /* Counter */ \
} pre##_counterctx; \
\
/* --- @pre_countergetiv@ --- * \
+++ /dev/null
-/* -*-c-*-
- *
- * Daft story for use in test encryptions
- *
- * (c) 1999 Straylight/Edgeware
- */
-
-/*----- Licensing notice --------------------------------------------------*
- *
- * This file is part of Catacomb.
- *
- * Catacomb is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Library General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * Catacomb is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with Catacomb; if not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
- */
-
-#ifndef CATACOMB_DAFTSTORY_H
-#define CATACOMB_DAFTSTORY_H
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-/*----- Macros ------------------------------------------------------------*/
-
-/* --- Don't ask --- */
-
-#ifdef SMALL_TEST
-# define TEXT "A small piece of text for testing encryption."
-#else
-# define STORY "\
-Once upon a time there were a beautiful princess, a slightly nutty wizard,\n\
-and a watermelon. Now, the watermelon had decided that it probably wasn't\n\
-going to get very far with the princess unless it did something pretty\n\
-drastic. So it asked the wizard to turn it into a handsome prince.\n\
-\n\
-At least, this is the way that the wizard viewed the situation. He might\n\
-have just hallucinated it all; those mushrooms had looked ever so nice.\n\
-\n\
-Back to the point. The watermelon had expressed its desire not to be a\n\
-watermelon any more. And the wizard was probably tripping something quite\n\
-powerful. He hunted around a bit for his staff, and mumbled something\n\
-that film directors would think of as sounding appropriately arcane and\n\
-mystical (but was, in fact, just the ingredients list for an ancient\n\
-remedy for athlete's foot) and *pop*. Cooked watermelon. Yuk.\n\
-\n\
-Later in the year, the princess tripped over the hem of her dress, fell\n\
-down a spiral staircase, and died. The king ordered dressmakers to attach\n\
-safety warnings to long dresses.\n\
-\n\
-And the wizard? Who cares?\n\
-"
-# define TEXT STORY STORY
-#endif
-
-#define KEY "Penguins rule OK, rhubarb cauliflower"
-#define IV "EdgewareCatacomb, parsley, sage, rosemary and thyme"
-
-/*----- That's all, folks -------------------------------------------------*/
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif
--- /dev/null
+/* -*-c-*-
+ *
+ * The EAX authenticated-encryption mode
+ *
+ * (c) 2017 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef CATACOMB_EAX_DEF_H
+#define CATACOMB_EAX_DEF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#ifndef CATACOMB_ARENA_H
+# include "arena.h"
+#endif
+
+#ifndef CATACOMB_BLKC_H
+# include "blkc.h"
+#endif
+
+#ifndef CATACOMB_CT_H
+# include "ct.h"
+#endif
+
+#ifndef CATACOMB_CMAC_H
+# include "cmac.h"
+#endif
+
+#ifndef CATACOMB_CMAC_DEF_H
+# include "cmac-def.h"
+#endif
+
+#ifndef CATACOMB_KEYSZ_H
+# include "keysz.h"
+#endif
+
+#ifndef CATACOMB_PARANOIA_H
+# include "paranoia.h"
+#endif
+
+#ifndef CATACOMB_RSVR_H
+# include "rsvr.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @EAX_DEF@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Creates an implementation for the EAX authenticated-
+ * encryption mode.
+ */
+
+#define EAX_DEF(PRE, pre) EAX_DEFX(PRE, pre, #pre, #pre)
+
+#define EAX_DEFX(PRE, pre, name, fname) \
+ \
+OMAC_DECL(PRE, pre) \
+ \
+const octet \
+ pre##_eaxnoncesz[] = { KSZ_ANY, PRE##_BLKSZ }, \
+ pre##_eaxtagsz[] = { KSZ_RANGE, PRE##_BLKSZ, 0, PRE##_BLKSZ, 1 }; \
+ \
+/* --- @pre_eaxsetkey@ --- * \
+ * \
+ * Arguments: @pre_eaxkey *key@ = pointer to key block to fill in \
+ * @const void *k@ = pointer to key material \
+ * @size_t ksz@ = size of key material \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes an EAX key block. \
+ */ \
+ \
+void pre##_eaxsetkey(pre##_eaxkey *key, const void *k, size_t ksz) \
+{ \
+ uint32 t[PRE##_BLKSZ/4]; \
+ \
+ /* Initialize the block cipher. */ \
+ pre##_init(&key->ctx, k, ksz); \
+ \
+ /* Set up the OMAC masks. */ \
+ pre##_omacmasks(&key->ctx, key->m0, key->m1); \
+ \
+ /* Set up the OMAC tweaks. EAX tweaks its MAC by simply stitching \
+ * magic block-wide prefixes %$t_0$%, %$t_1$%, %$t_2$% (which are \
+ * simply the numbers 0, 1, 2) on the front of strings. We can \
+ * accelerate things by caching two values for each tweak: \
+ * \
+ * * %$v_i = E_K(t_i)$% is the accumulator that results from \
+ * pushing the tweak through the blockcipher, which we'd \
+ * calculate if the original message was nonempty. \
+ * \
+ * * %$z_i = E_K(t_0 \xor m_0)$% is the tweak with the `full final \
+ * buffer' mask applied, which is the final tag for a final empty \
+ * message. \
+ */ \
+ BLKC_BSET(PRE, t, 0); pre##_eblk(&key->ctx, t, key->v0); \
+ BLKC_XMOVE(PRE, t, key->m0); pre##_eblk(&key->ctx, t, key->z0); \
+ BLKC_BSET(PRE, t, 1); pre##_eblk(&key->ctx, t, key->v1); \
+ BLKC_XMOVE(PRE, t, key->m0); pre##_eblk(&key->ctx, t, key->z1); \
+ BLKC_BSET(PRE, t, 2); pre##_eblk(&key->ctx, t, key->v2); \
+ BLKC_XMOVE(PRE, t, key->m0); pre##_eblk(&key->ctx, t, key->z2); \
+} \
+ \
+/* --- @pre_eaxaadinit@ --- * \
+ * \
+ * Arguments: @pre_eaxaadctx *aad@ = pointer to AAD context \
+ * @const pre_eaxkey *key@ = pointer to key block \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes an EAX AAD (`additional authenticated \
+ * data') context associated with a given key. AAD \
+ * contexts can be copied and/or reused, saving time if \
+ * the AAD for a number of messages has a common prefix. \
+ * \
+ * The @key@ doesn't need to be kept around, though \
+ * usually there'll at least be another copy in some EAX \
+ * operation context because the AAD on its own isn't much \
+ * good. \
+ */ \
+ \
+void pre##_eaxaadinit(pre##_eaxaadctx *aad, const pre##_eaxkey *key) \
+ { aad->k = *key; aad->off = 0; BLKC_MOVE(PRE, aad->a, key->v1); } \
+ \
+/* --- @pre_eaxaadhash@ --- * \
+ * \
+ * Arguments: @pre_eaxaadctx *aad@ = pointer to AAD context \
+ * @const void *p@ = pointer to AAD material \
+ * @size_t sz@ = length of AAD material \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Feeds AAD into the context. \
+ */ \
+ \
+void pre##_eaxaadhash(pre##_eaxaadctx *aad, const void *p, size_t sz) \
+{ \
+ rsvr_state st; \
+ const octet *q; \
+ \
+ rsvr_setup(&st, &pre##_omacpolicy, aad->b, &aad->off, p, sz); \
+ RSVR_DO(&st) while ((q = RSVR_NEXT(&st, PRE##_BLKSZ)) != 0) \
+ OMAC_BLOCK(PRE, pre, &aad->k.ctx, aad->a, q); \
+} \
+ \
+/* --- @pre_eaxinit@ --- * \
+ * \
+ * Arguments: @pre_eaxctx *ctx@ = pointer to EAX context \
+ * @const pre_eaxkey *key@ = pointer to key block \
+ * @const void *n@ = pointer to nonce \
+ * @size_t nsz@ = size of nonce \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initialize an EAX operation context with a given key. \
+ * \
+ * The original key needn't be kept around any more. \
+ */ \
+ \
+void pre##_eaxinit(pre##_eaxctx *ctx, const pre##_eaxkey *k, \
+ const void *n, size_t nsz) \
+ { ctx->k = *k; pre##_eaxreinit(ctx, n, nsz); } \
+ \
+/* --- @pre_eaxreinit@ --- * \
+ * \
+ * Arguments: @pre_eaxctx *ctx@ = pointer to EAX context \
+ * @const void *n@ = pointer to nonce \
+ * @size_t nsz@ = size of nonce \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Reinitialize an EAX operation context, changing the \
+ * nonce. \
+ */ \
+ \
+void pre##_eaxreinit(pre##_eaxctx *ctx, const void *n, size_t nsz) \
+{ \
+ octet b[PRE##_BLKSZ]; \
+ const octet *q = n; \
+ \
+ /* Initialize the OMAC context with the right tweak. */ \
+ BLKC_MOVE(PRE, ctx->a, ctx->k.v2); \
+ ctx->off = 0; \
+ \
+ /* Calculate the initial counter from the nonce. This is OMAC again, \
+ * but this time we know that we're starting from a clean slate and \
+ * we have the whole input in one go, so we don't bother with the \
+ * full reservoir machinery. \
+ */ \
+ if (!nsz) \
+ BLKC_MOVE(PRE, ctx->c0, ctx->k.z0); \
+ else { \
+ BLKC_MOVE(PRE, ctx->c0, ctx->k.v0); \
+ while (nsz > PRE##_BLKSZ) { \
+ OMAC_BLOCK(PRE, pre, &ctx->k.ctx, ctx->c0, q); \
+ q += PRE##_BLKSZ; nsz -= PRE##_BLKSZ; \
+ } \
+ memcpy(b, q, nsz); \
+ pre##_omacdone(&ctx->k.ctx, ctx->k.m0, ctx->k.m1, \
+ ctx->c0, b, nsz); \
+ } \
+ \
+ /* We must remember the initial counter for the final tag \
+ * calculation. (I conjecture that storing the final counter instead \
+ * would be just as secure, and require less state, but I've not \
+ * proven this, and anyway it wouldn't interoperate.) Copy it to \
+ * make the working counter. \
+ */ \
+ BLKC_MOVE(PRE, ctx->c, ctx->c0); \
+} \
+ \
+/* --- @pre_eaxencrypt@ --- * \
+ * \
+ * Arguments: @pre_eaxctx *ctx@ = pointer to EAX operation context \
+ * @const void *src@ = pointer to plaintext message chunk \
+ * @size_t sz@ = size of the plaintext \
+ * @buf *dst@ = a buffer to write the ciphertext to \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Encrypts a chunk of a plaintext message, writing a \
+ * chunk of ciphertext to the output buffer and updating \
+ * the operation state. \
+ * \
+ * For EAX, we always write a ciphertext chunk the same \
+ * size as the plaintext. The messing about with @buf@ \
+ * objects makes the interface consistent with other AEAD \
+ * schemes which can't do this. \
+ */ \
+ \
+int pre##_eaxencrypt(pre##_eaxctx *ctx, \
+ const void *src, size_t sz, buf *dst) \
+{ \
+ rsvr_plan plan; \
+ uint32 t[PRE##_BLKSZ/4]; \
+ const octet *p = src; \
+ octet *q, *r, y; \
+ \
+ /* Allocate space for the ciphertext. */ \
+ if (sz) { q = buf_get(dst, sz); if (!q) return (-1); } \
+ else q = 0; \
+ \
+ /* Determine the buffering plan. Our buffer is going to do double- \
+ * duty here. The end portion is going to contain mask from the \
+ * encrypted counter which we mix into the plaintext to encrypt it; \
+ * the start portion, which originally mask bytes we've already used, \
+ * will hold the output ciphertext, which will eventually be \
+ * collected into the OMAC state. \
+ */ \
+ rsvr_mkplan(&plan, &pre##_omacpolicy, ctx->off, sz); \
+ \
+ /* Initial portion, fulfilled from the buffer. If the buffer is \
+ * empty, then that means that we haven't yet encrypted the current \
+ * counter, so we should do that and advance it. \
+ */ \
+ if (plan.head) { \
+ if (!ctx->off) { \
+ pre##_eblk(&ctx->k.ctx, ctx->c, t); BLKC_BSTEP(PRE, ctx->c); \
+ BLKC_STORE(PRE, ctx->b, t); \
+ } \
+ r = ctx->b + ctx->off; ctx->off += plan.head; \
+ while (plan.head--) { y = *p++ ^ *r; *r++ = *q++ = y; } \
+ } \
+ \
+ /* If we've filled up the buffer then we need to cycle the MAC and \
+ * reset the offset. \
+ */ \
+ if (plan.from_rsvr) { \
+ OMAC_BLOCK(PRE, pre, &ctx->k.ctx, ctx->a, ctx->b); \
+ ctx->off = 0; \
+ } \
+ \
+ /* Now to process the main body of the input. We sneakily open-code \
+ * the OMAC part of this. \
+ */ \
+ while (plan.from_input) { \
+ pre##_eblk(&ctx->k.ctx, ctx->c, t); BLKC_BSTEP(PRE, ctx->c); \
+ BLKC_XLOAD(PRE, t, p); p += PRE##_BLKSZ; \
+ BLKC_STORE(PRE, q, t); q += PRE##_BLKSZ; \
+ BLKC_XMOVE(PRE, ctx->a, t); pre##_eblk(&ctx->k.ctx, ctx->a, ctx->a); \
+ plan.from_input -= PRE##_BLKSZ; \
+ } \
+ \
+ /* Finally, deal with any final portion. If there is one, we know \
+ * that the buffer is empty: we must have filled it above, or this \
+ * would all count as `initial' data. \
+ */ \
+ if (plan.tail) { \
+ pre##_eblk(&ctx->k.ctx, ctx->c, t); BLKC_BSTEP(PRE, ctx->c); \
+ BLKC_STORE(PRE, ctx->b, t); \
+ r = ctx->b; ctx->off += plan.tail; \
+ while (plan.tail--) { y = *p++ ^ *r; *r++ = *q++ = y; } \
+ } \
+ \
+ /* And we're done. */ \
+ return (0); \
+} \
+ \
+/* --- @pre_eaxdecrypt@ --- * \
+ * \
+ * Arguments: @pre_eaxctx *ctx@ = pointer to EAX operation context \
+ * @const void *src@ = pointer to ciphertext message chunk \
+ * @size_t sz@ = size of the ciphertext \
+ * @buf *dst@ = a buffer to write the plaintext to \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Decrypts a chunk of a ciphertext message, writing a \
+ * chunk of plaintext to the output buffer and updating \
+ * the operation state. \
+ * \
+ * For EAX, we always write a plaintext chunk the same \
+ * size as the ciphertext. The messing about with @buf@ \
+ * objects makes the interface consistent with other AEAD \
+ * schemes which can't do this. \
+ */ \
+ \
+int pre##_eaxdecrypt(pre##_eaxctx *ctx, \
+ const void *src, size_t sz, buf *dst) \
+{ \
+ rsvr_plan plan; \
+ uint32 t[PRE##_BLKSZ/4], u[PRE##_BLKSZ]; \
+ const octet *p = src; \
+ octet *q, *r, y; \
+ \
+ /* Allocate space for the plaintext. */ \
+ if (sz) { q = buf_get(dst, sz); if (!q) return (-1); } \
+ else q = 0; \
+ \
+ /* Determine the buffering plan. Our buffer is going to do double- \
+ * duty here. The end portion is going to contain mask from the \
+ * encrypted counter which we mix into the plaintext to encrypt it; \
+ * the start portion, which originally mask bytes we've already used, \
+ * will hold the input ciphertext, which will eventually be \
+ * collected into the OMAC state. \
+ */ \
+ rsvr_mkplan(&plan, &pre##_omacpolicy, ctx->off, sz); \
+ \
+ /* Initial portion, fulfilled from the buffer. If the buffer is \
+ * empty, then that means that we haven't yet encrypted the current \
+ * counter, so we should do that and advance it. \
+ */ \
+ if (plan.head) { \
+ if (!ctx->off) { \
+ pre##_eblk(&ctx->k.ctx, ctx->c, t); BLKC_BSTEP(PRE, ctx->c); \
+ BLKC_STORE(PRE, ctx->b, t); \
+ } \
+ r = ctx->b + ctx->off; ctx->off += plan.head; \
+ while (plan.head--) { y = *p++; *q++ = y ^ *r; *r++ = y; } \
+ } \
+ \
+ /* If we've filled up the buffer then we need to cycle the MAC and \
+ * reset the offset. \
+ */ \
+ if (plan.from_rsvr) { \
+ OMAC_BLOCK(PRE, pre, &ctx->k.ctx, ctx->a, ctx->b); \
+ ctx->off = 0; \
+ } \
+ \
+ /* Now to process the main body of the input. We sneakily open-code \
+ * the OMAC part of this. \
+ */ \
+ while (plan.from_input) { \
+ pre##_eblk(&ctx->k.ctx, ctx->c, t); BLKC_BSTEP(PRE, ctx->c); \
+ BLKC_LOAD(PRE, u, p); p += PRE##_BLKSZ; \
+ BLKC_XSTORE(PRE, q, t, u); q += PRE##_BLKSZ; \
+ BLKC_XMOVE(PRE, ctx->a, u); pre##_eblk(&ctx->k.ctx, ctx->a, ctx->a); \
+ plan.from_input -= PRE##_BLKSZ; \
+ } \
+ \
+ /* Finally, deal with any final portion. If there is one, we know \
+ * that the buffer is empty: we must have filled it above, or this \
+ * would all count as `initial' data. \
+ */ \
+ if (plan.tail) { \
+ pre##_eblk(&ctx->k.ctx, ctx->c, t); BLKC_BSTEP(PRE, ctx->c); \
+ BLKC_STORE(PRE, ctx->b, t); \
+ r = ctx->b; ctx->off += plan.tail; \
+ while (plan.tail--) { y = *p++; *q++ = y ^ *r; *r++ = y; } \
+ } \
+ \
+ /* And we're done. */ \
+ return (0); \
+} \
+ \
+/* --- @pre_eaxtag@ --- * \
+ * \
+ * Arguments: @pre_eaxctx *ctx@ = pointer to an EAX context \
+ * @const pre_eaxaadctx *aad@ = pointer to AAD context, or \
+ * null \
+ * @octet *t@ = where to write a (full-length) tag \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Finishes an EAX operation, by calculating the tag. \
+ */ \
+ \
+static void pre##_eaxtag(pre##_eaxctx *ctx, \
+ const pre##_eaxaadctx *aad, octet *t) \
+{ \
+ octet b[PRE##_BLKSZ]; \
+ uint32 u[PRE##_BLKSZ/4]; \
+ \
+ /* Finish tagging the ciphertext. (The buffer is empty if and only \
+ * if there was no message, since the OMAC reservoir policy leaves \
+ * the buffer full.) \
+ */ \
+ if (!ctx->off) BLKC_MOVE(PRE, ctx->a, ctx->k.z2); \
+ else pre##_omacdone(&ctx->k.ctx, ctx->k.m0, ctx->k.m1, \
+ ctx->a, ctx->b, ctx->off); \
+ \
+ /* If there's no AAD, because the pointer is null or no data was \
+ * supplied, then use the cached empty-header tag. Otherwise \
+ * calculate the tag for the AAD. Either way, mix the result into \
+ * ctx->A, and be careful not to modify the AAD context. (Again, the \
+ * buffer is empty if and only if there was no AAD.) \
+ */ \
+ if (!aad || !aad->off) BLKC_XMOVE(PRE, ctx->a, ctx->k.z1); \
+ else { \
+ BLKC_MOVE(PRE, u, aad->a); memcpy(b, aad->b, aad->off); \
+ pre##_omacdone(&ctx->k.ctx, ctx->k.m0, ctx->k.m1, u, b, aad->off); \
+ BLKC_XMOVE(PRE, ctx->a, u); \
+ } \
+ \
+ /* Finally, mix in the initial counter value. */ \
+ BLKC_XMOVE(PRE, ctx->a, ctx->c0); \
+ \
+ /* We're done. */ \
+ BLKC_STORE(PRE, t, ctx->a); \
+} \
+ \
+/* --- @pre_eaxencryptdone@ --- * \
+ * \
+ * Arguments: @pre_eaxctx *ctx@ = pointer to an EAX context \
+ * @const pre_eaxaadctx *aad@ = pointer to AAD context, or \
+ * null \
+ * @buf *dst@ = buffer for remaining ciphertext \
+ * @void *tag@ = where to write the tag \
+ * @size_t tsz@ = length of tag to store \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Completes an EAX encryption operation. The @aad@ \
+ * pointer may be null if there is no additional \
+ * authenticated data. EAX doesn't buffer ciphertext, but \
+ * the output buffer is provided anyway for consistency \
+ * with other AEAD schemes which don't have this property; \
+ * the function will fail if the output buffer is broken. \
+ */ \
+ \
+int pre##_eaxencryptdone(pre##_eaxctx *ctx, \
+ const pre##_eaxaadctx *aad, buf *dst, \
+ void *tag, size_t tsz) \
+{ \
+ octet t[PRE##_BLKSZ]; \
+ \
+ if (tsz > PRE##_BLKSZ) return (-1); \
+ if (!BOK(dst)) return (-1); \
+ pre##_eaxtag(ctx, aad, t); memcpy(tag, t, tsz); \
+ return (0); \
+} \
+ \
+/* --- @pre_eaxdecryptdone@ --- * \
+ * \
+ * Arguments: @pre_eaxctx *ctx@ = pointer to an EAX context \
+ * @const pre_eaxaadctx *aad@ = pointer to AAD context, or \
+ * null \
+ * @buf *dst@ = buffer for remaining plaintext \
+ * @const void *tag@ = tag to verify \
+ * @size_t tsz@ = length of tag \
+ * \
+ * Returns: @+1@ for complete success; @0@ if tag verification \
+ * failed; @-1@ for other kinds of errors. \
+ * \
+ * Use: Completes an EAX decryption operation. The @aad@ \
+ * pointer may be null if there is no additional \
+ * authenticated data. EAX doesn't buffer plaintext, but \
+ * the output buffer is provided anyway for consistency \
+ * with other AEAD schemes which don't have this property; \
+ * the function will fail if the output buffer is broken. \
+ */ \
+ \
+int pre##_eaxdecryptdone(pre##_eaxctx *ctx, \
+ const pre##_eaxaadctx *aad, buf *dst, \
+ const void *tag, size_t tsz) \
+{ \
+ octet t[PRE##_BLKSZ]; \
+ \
+ if (tsz > PRE##_BLKSZ) return (-1); \
+ if (!BOK(dst)) return (-1); \
+ pre##_eaxtag(ctx, aad, t); \
+ if (!ct_memeq(tag, t, tsz)) return (0); \
+ else return (+1); \
+} \
+ \
+/* --- Generic AEAD interface --- */ \
+ \
+typedef struct gactx { \
+ gaead_aad a; \
+ pre##_eaxaadctx aad; \
+} gactx; \
+ \
+ \
+static gaead_aad *gadup(const gaead_aad *a) \
+ { gactx *aad = S_CREATE(gactx); *aad = *(gactx *)a; return (&aad->a); } \
+ \
+static void gahash(gaead_aad *a, const void *h, size_t hsz) \
+ { gactx *aad = (gactx *)a; pre##_eaxaadhash(&aad->aad, h, hsz); } \
+ \
+static void gadestroy(gaead_aad *a) \
+ { gactx *aad = (gactx *)a; BURN(*aad); S_DESTROY(aad); } \
+ \
+static const gaead_aadops gaops = \
+ { &pre##_eax, gadup, gahash, gadestroy }; \
+ \
+static gaead_aad *gaad(const pre##_eaxkey *k) \
+{ \
+ gactx *aad = S_CREATE(gactx); \
+ aad->a.ops = &gaops; \
+ pre##_eaxaadinit(&aad->aad, k); \
+ return (&aad->a); \
+} \
+ \
+typedef struct gectx { \
+ gaead_enc e; \
+ pre##_eaxctx ctx; \
+} gectx; \
+ \
+static gaead_aad *geaad(gaead_enc *e) \
+ { gectx *enc = (gectx *)e; return (gaad(&enc->ctx.k)); } \
+ \
+static int gereinit(gaead_enc *e, const void *n, size_t nsz, \
+ size_t hsz, size_t msz, size_t tsz) \
+{ \
+ gectx *enc = (gectx *)e; \
+ \
+ if (tsz > PRE##_BLKSZ) return (-1); \
+ pre##_eaxreinit(&enc->ctx, n, nsz); \
+ return (0); \
+} \
+ \
+static int geenc(gaead_enc *e, const void *m, size_t msz, buf *b) \
+{ \
+ gectx *enc = (gectx *)e; \
+ return (pre##_eaxencrypt(&enc->ctx, m, msz, b)); \
+} \
+ \
+static int gedone(gaead_enc *e, const gaead_aad *a, \
+ buf *b, void *t, size_t tsz) \
+{ \
+ gectx *enc = (gectx *)e; gactx *aad = (gactx *)a; \
+ assert(!a || a->ops == &gaops); \
+ return (pre##_eaxencryptdone(&enc->ctx, a ? &aad->aad : 0, b, t, tsz)); \
+} \
+ \
+static void gedestroy(gaead_enc *e) \
+ { gectx *enc = (gectx *)e; BURN(*enc); S_DESTROY(enc); } \
+ \
+static const gaead_encops geops = \
+ { &pre##_eax, geaad, gereinit, geenc, gedone, gedestroy }; \
+ \
+typedef struct gdctx { \
+ gaead_dec d; \
+ pre##_eaxctx ctx; \
+} gdctx; \
+ \
+static gaead_aad *gdaad(gaead_dec *d) \
+ { gdctx *dec = (gdctx *)d; return (gaad(&dec->ctx.k)); } \
+ \
+static int gdreinit(gaead_dec *d, const void *n, size_t nsz, \
+ size_t hsz, size_t csz, size_t tsz) \
+{ \
+ gdctx *dec = (gdctx *)d; \
+ \
+ if (tsz > PRE##_BLKSZ) return (-1); \
+ pre##_eaxreinit(&dec->ctx, n, nsz); \
+ return (0); \
+} \
+ \
+static int gddec(gaead_dec *d, const void *c, size_t csz, buf *b) \
+{ \
+ gdctx *dec = (gdctx *)d; \
+ return (pre##_eaxdecrypt(&dec->ctx, c, csz, b)); \
+} \
+ \
+static int gddone(gaead_dec *d, const gaead_aad *a, \
+ buf *b, const void *t, size_t tsz) \
+{ \
+ gdctx *dec = (gdctx *)d; gactx *aad = (gactx *)a; \
+ assert(!a || a->ops == &gaops); \
+ return (pre##_eaxdecryptdone(&dec->ctx, a ? &aad->aad : 0, b, t, tsz)); \
+} \
+ \
+static void gddestroy(gaead_dec *d) \
+ { gdctx *dec = (gdctx *)d; BURN(*dec); S_DESTROY(dec); } \
+ \
+static const gaead_decops gdops = \
+ { &pre##_eax, gdaad, gdreinit, gddec, gddone, gddestroy }; \
+ \
+typedef struct gkctx { \
+ gaead_key k; \
+ pre##_eaxkey key; \
+} gkctx; \
+ \
+static gaead_aad *gkaad(const gaead_key *k) \
+ { gkctx *key = (gkctx *)k; return (gaad(&key->key)); } \
+ \
+static gaead_enc *gkenc(const gaead_key *k, const void *n, size_t nsz, \
+ size_t hsz, size_t msz, size_t tsz) \
+{ \
+ gkctx *key = (gkctx *)k; \
+ gectx *enc; \
+ \
+ if (tsz > PRE##_BLKSZ) return (0); \
+ enc = S_CREATE(gectx); enc->e.ops = &geops; \
+ pre##_eaxinit(&enc->ctx, &key->key, n, nsz); \
+ return (&enc->e); \
+} \
+ \
+static gaead_dec *gkdec(const gaead_key *k, const void *n, size_t nsz, \
+ size_t hsz, size_t csz, size_t tsz) \
+{ \
+ gkctx *key = (gkctx *)k; \
+ gdctx *dec; \
+ \
+ if (tsz > PRE##_BLKSZ) return (0); \
+ dec = S_CREATE(gdctx); dec->d.ops = &gdops; \
+ pre##_eaxinit(&dec->ctx, &key->key, n, nsz); \
+ return (&dec->d); \
+} \
+ \
+static void gkdestroy(gaead_key *k) \
+ { gkctx *key = (gkctx *)k; BURN(*key); S_DESTROY(key); } \
+ \
+static const gaead_keyops gkops = \
+ { &pre##_eax, gkaad, gkenc, gkdec, gkdestroy }; \
+ \
+static gaead_key *gckey(const void *k, size_t ksz) \
+{ \
+ gkctx *key = S_CREATE(gkctx); \
+ key->k.ops = &gkops; \
+ pre##_eaxsetkey(&key->key, k, ksz); \
+ return (&key->k); \
+} \
+ \
+const gcaead pre##_eax = { \
+ name "-eax", \
+ pre##_keysz, pre##_eaxnoncesz, pre##_eaxtagsz, \
+ PRE##_BLKSZ, 0, 0, 0, \
+ gckey \
+}; \
+ \
+EAX_TESTX(PRE, pre, name, fname)
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#define EAX_TEST(PRE, pre) EAX_TESTX(PRE, pre, #pre, #pre)
+
+/* --- @EAX_TEST@ --- *
+ *
+ * Arguments: @PRE, pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Standard test rig for EAX functions.
+ */
+
+#ifdef TEST_RIG
+
+#include <stdio.h>
+
+#include <mLib/dstr.h>
+#include <mLib/quis.h>
+#include <mLib/testrig.h>
+
+#define EAX_TESTX(PRE, pre, name, fname) \
+ \
+static int eaxverify(dstr *v) \
+{ \
+ pre##_eaxkey key; \
+ pre##_eaxaadctx aad; \
+ pre##_eaxctx ctx; \
+ int ok = 1, win; \
+ int i; \
+ octet *p; \
+ int szs[] = { 1, 7, 192, -1, 0 }, *ip; \
+ size_t hsz, msz; \
+ dstr d = DSTR_INIT, t = DSTR_INIT; \
+ buf b; \
+ \
+ dstr_ensure(&d, v[4].len > v[3].len ? v[4].len : v[3].len); \
+ dstr_ensure(&t, v[5].len); t.len = v[5].len; \
+ \
+ pre##_eaxsetkey(&key, v[0].buf, v[0].len); \
+ \
+ for (ip = szs; *ip; ip++) { \
+ \
+ pre##_eaxinit(&ctx, &key, (octet *)v[1].buf, v[1].len); \
+ \
+ i = *ip; \
+ hsz = v[2].len; \
+ if (i == -1) i = hsz; \
+ if (i > hsz) continue; \
+ p = (octet *)v[2].buf; \
+ pre##_eaxaadinit(&aad, &key); \
+ while (hsz) { \
+ if (i > hsz) i = hsz; \
+ pre##_eaxaadhash(&aad, p, i); \
+ p += i; hsz -= i; \
+ } \
+ \
+ buf_init(&b, d.buf, d.sz); \
+ i = *ip; \
+ msz = v[3].len; \
+ if (i == -1) i = msz; \
+ if (i > msz) continue; \
+ p = (octet *)v[3].buf; \
+ while (msz) { \
+ if (i > msz) i = msz; \
+ if (pre##_eaxencrypt(&ctx, p, i, &b)) { \
+ puts("!! eaxencrypt reports failure"); \
+ goto fail_enc; \
+ } \
+ p += i; msz -= i; \
+ } \
+ \
+ if (pre##_eaxencryptdone(&ctx, &aad, &b, (octet *)t.buf, t.len)) { \
+ puts("!! eaxencryptdone reports failure"); \
+ goto fail_enc; \
+ } \
+ d.len = BLEN(&b); \
+ \
+ if (d.len != v[4].len || \
+ memcmp(d.buf, v[4].buf, v[4].len) != 0 || \
+ memcmp(t.buf, v[5].buf, v[5].len) != 0) { \
+ fail_enc: \
+ printf("\nfail encrypt:\n\tstep = %i", *ip); \
+ fputs("\n\tkey = ", stdout); type_hex.dump(&v[0], stdout); \
+ fputs("\n\tnonce = ", stdout); type_hex.dump(&v[1], stdout); \
+ fputs("\n\theader = ", stdout); type_hex.dump(&v[2], stdout); \
+ fputs("\n\tmessage = ", stdout); type_hex.dump(&v[3], stdout); \
+ fputs("\n\texp ct = ", stdout); type_hex.dump(&v[4], stdout); \
+ fputs("\n\tcalc ct = ", stdout); type_hex.dump(&d, stdout); \
+ fputs("\n\texp tag = ", stdout); type_hex.dump(&v[5], stdout); \
+ fputs("\n\tcalc tag = ", stdout); type_hex.dump(&t, stdout); \
+ putchar('\n'); \
+ ok = 0; \
+ } \
+ \
+ pre##_eaxinit(&ctx, &key, (octet *)v[1].buf, v[1].len); \
+ \
+ buf_init(&b, d.buf, d.sz); \
+ i = *ip; \
+ msz = v[4].len; \
+ if (i == -1) i = msz; \
+ if (i > msz) continue; \
+ p = (octet *)v[4].buf; \
+ while (msz) { \
+ if (i > msz) i = msz; \
+ if (pre##_eaxdecrypt(&ctx, p, i, &b)) { \
+ puts("!! eaxdecrypt reports failure"); \
+ win = 0; goto fail_dec; \
+ } \
+ p += i; msz -= i; \
+ } \
+ \
+ win = pre##_eaxdecryptdone(&ctx, &aad, &b, \
+ (octet *)v[5].buf, v[5].len); \
+ if (win < 0) { \
+ puts("!! eaxdecryptdone reports failure"); \
+ goto fail_dec; \
+ } \
+ d.len = BLEN(&b); \
+ \
+ if (d.len != v[3].len || !win || \
+ memcmp(d.buf, v[3].buf, v[3].len) != 0) { \
+ fail_dec: \
+ printf("\nfail decrypt:\n\tstep = %i", *ip); \
+ fputs("\n\tkey = ", stdout); type_hex.dump(&v[0], stdout); \
+ fputs("\n\tnonce = ", stdout); type_hex.dump(&v[1], stdout); \
+ fputs("\n\theader = ", stdout); type_hex.dump(&v[2], stdout); \
+ fputs("\n\tciphertext = ", stdout); type_hex.dump(&v[4], stdout); \
+ fputs("\n\texp pt = ", stdout); type_hex.dump(&v[3], stdout); \
+ fputs("\n\tcalc pt = ", stdout); type_hex.dump(&d, stdout); \
+ fputs("\n\ttag = ", stdout); type_hex.dump(&v[5], stdout); \
+ printf("\n\tverify %s", win ? "ok" : "FAILED"); \
+ putchar('\n'); \
+ ok = 0; \
+ } \
+ } \
+ \
+ dstr_destroy(&d); dstr_destroy(&t); \
+ return (ok); \
+} \
+ \
+static test_chunk aeaddefs[] = { \
+ { name "-eax", eaxverify, \
+ { &type_hex, &type_hex, &type_hex, &type_hex, \
+ &type_hex, &type_hex, 0 } }, \
+ { 0, 0, { 0 } } \
+}; \
+ \
+int main(int argc, char *argv[]) \
+{ \
+ ego(argv[0]); \
+ test_run(argc, argv, aeaddefs, SRCDIR"/t/" fname); \
+ return (0); \
+}
+
+#else
+# define EAX_TESTX(PRE, pre, name, fname)
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
--- /dev/null
+/* -*-c-*-
+ *
+ * The EAX authenticated-encryption mode
+ *
+ * (c) 2017 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*----- Notes on EAX ------------------------------------------------------*
+ *
+ * The name doesn't appear to be short for anything convincing. EAX was
+ * designed in 2004 by Mihir Bellare, Phillip Rogaway, and David Wagner, as a
+ * response to CCM's deficiencies, which Rogaway and Wagner had complained
+ * about the previous year. Like CCM, it's a patent-free authenticated
+ * encryption scheme based on counter mode and CBC-MAC, and needs two
+ * blockcipher applications per message block, but it's much more refined
+ * than CCM. The EAX specification is clear about how the mode applies to
+ * arbitrary block sizes, and I've not had to make any decisions on how to
+ * extend it myself.
+ *
+ * EAX allows arbitrarily sized nonces, and doesn't require precommitment to
+ * any lengths, and allows header data to be processed independently of any
+ * message. It's basically about as good as a rate-1/2 scheme is going to
+ * be.
+ */
+
+#ifndef CATACOMB_EAX_H
+#define CATACOMB_EAX_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+#include <mLib/buf.h>
+
+#ifndef CATACOMB_GAEAD_H
+# include "gaead.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @EAX_DECL@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Creates declarations for EAX authenticated-encryption mode.
+ */
+
+#define EAX_DECL(PRE, pre) \
+ \
+typedef struct pre##_eaxkey { \
+ pre##_ctx ctx; /* Block cipher key */ \
+ uint32 m0[PRE##_BLKSZ/4], m1[PRE##_BLKSZ/4]; /* Final OMAC masks */ \
+ uint32 v0[PRE##_BLKSZ/4], /* OMAC tweak accumulators */ \
+ v1[PRE##_BLKSZ/4], v2[PRE##_BLKSZ/4]; \
+ uint32 z0[PRE##_BLKSZ/4], /* Empty-message tag values */ \
+ z1[PRE##_BLKSZ/4], z2[PRE##_BLKSZ/4]; \
+} pre##_eaxkey; \
+ \
+typedef struct pre##_eaxaadctx { \
+ pre##_eaxkey k; /* Underlying key */ \
+ uint32 a[PRE##_BLKSZ/4]; /* OMAC accumulator */ \
+ octet b[PRE##_BLKSZ]; /* Input buffer */ \
+ unsigned off; /* Length of stuff in buffer */ \
+} pre##_eaxaadctx; \
+ \
+typedef struct pre##_eaxctx { \
+ /* The buffer is split into two portions. The first N octets hold a \
+ * chunk of ciphertext, which will be fed into the OMAC calculation; \
+ * the remaining BLKSZ - N octets hold E_K(C), which is the XOR mask \
+ * to apply to the plaintext or ciphertext. \
+ */ \
+ pre##_eaxkey k; /* Underlying key */ \
+ uint32 c[PRE##_BLKSZ/4]; /* Current counter value */ \
+ uint32 c0[PRE##_BLKSZ/4]; /* Initial counter */ \
+ uint32 a[PRE##_BLKSZ]; /* OMAC accumulator */ \
+ octet b[PRE##_BLKSZ]; /* Ciphertext/mask buffer */ \
+ unsigned off; /* Crossover point in buffer */ \
+} pre##_eaxctx; \
+ \
+extern const octet pre##_eaxnoncesz[], pre##_eaxtagsz[]; \
+ \
+/* --- @pre_eaxsetkey@ --- * \
+ * \
+ * Arguments: @pre_eaxkey *key@ = pointer to key block to fill in \
+ * @const void *k@ = pointer to key material \
+ * @size_t ksz@ = size of key material \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes an EAX key block. \
+ */ \
+ \
+extern void pre##_eaxsetkey(pre##_eaxkey */*key*/, \
+ const void */*k*/, size_t /*ksz*/); \
+ \
+/* --- @pre_eaxaadinit@ --- * \
+ * \
+ * Arguments: @pre_eaxaadctx *aad@ = pointer to AAD context \
+ * @const pre_eaxkey *key@ = pointer to key block \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes an EAX AAD (`additional authenticated \
+ * data') context associated with a given key. AAD \
+ * contexts can be copied and/or reused, saving time if \
+ * the AAD for a number of messages has a common prefix. \
+ * \
+ * The @key@ doesn't need to be kept around, though \
+ * usually there'll at least be another copy in some EAX \
+ * operation context because the AAD on its own isn't much \
+ * good. \
+ */ \
+ \
+extern void pre##_eaxaadinit(pre##_eaxaadctx */*aad*/, \
+ const pre##_eaxkey */*key*/); \
+ \
+/* --- @pre_eaxaadhash@ --- * \
+ * \
+ * Arguments: @pre_eaxaadctx *aad@ = pointer to AAD context \
+ * @const void *p@ = pointer to AAD material \
+ * @size_t sz@ = length of AAD material \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Feeds AAD into the context. \
+ */ \
+ \
+extern void pre##_eaxaadhash(pre##_eaxaadctx */*aad*/, \
+ const void */*p*/, size_t /*sz*/); \
+ \
+/* --- @pre_eaxinit@ --- * \
+ * \
+ * Arguments: @pre_eaxctx *ctx@ = pointer to EAX context \
+ * @const pre_eaxkey *key@ = pointer to key block \
+ * @const void *n@ = pointer to nonce \
+ * @size_t nsz@ = size of nonce \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initialize an EAX operation context with a given key. \
+ * \
+ * The original key needn't be kept around any more. \
+ */ \
+ \
+extern void pre##_eaxinit(pre##_eaxctx */*ctx*/, \
+ const pre##_eaxkey */*k*/, \
+ const void */*n*/, size_t /*nsz*/); \
+ \
+/* --- @pre_eaxreinit@ --- * \
+ * \
+ * Arguments: @pre_eaxctx *ctx@ = pointer to EAX context \
+ * @const void *n@ = pointer to nonce \
+ * @size_t nsz@ = size of nonce \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Reinitialize an EAX operation context, changing the \
+ * nonce. \
+ */ \
+ \
+extern void pre##_eaxreinit(pre##_eaxctx */*ctx*/, \
+ const void */*n*/, size_t /*nsz*/); \
+ \
+/* --- @pre_eaxencrypt@ --- * \
+ * \
+ * Arguments: @pre_eaxctx *ctx@ = pointer to EAX operation context \
+ * @const void *src@ = pointer to plaintext message chunk \
+ * @size_t sz@ = size of the plaintext \
+ * @buf *dst@ = a buffer to write the ciphertext to \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Encrypts a chunk of a plaintext message, writing a \
+ * chunk of ciphertext to the output buffer and updating \
+ * the operation state. \
+ * \
+ * For EAX, we always write a ciphertext chunk the same \
+ * size as the plaintext. The messing about with @buf@ \
+ * objects makes the interface consistent with other AEAD \
+ * schemes which can't do this. \
+ */ \
+ \
+extern int pre##_eaxencrypt(pre##_eaxctx */*ctx*/, \
+ const void */*src*/, size_t /*sz*/, \
+ buf */*dst*/); \
+ \
+/* --- @pre_eaxdecrypt@ --- * \
+ * \
+ * Arguments: @pre_eaxctx *ctx@ = pointer to EAX operation context \
+ * @const void *src@ = pointer to ciphertext message chunk \
+ * @size_t sz@ = size of the ciphertext \
+ * @buf *dst@ = a buffer to write the plaintext to \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Decrypts a chunk of a ciphertext message, writing a \
+ * chunk of plaintext to the output buffer and updating \
+ * the operation state. \
+ * \
+ * For EAX, we always write a plaintext chunk the same \
+ * size as the ciphertext. The messing about with @buf@ \
+ * objects makes the interface consistent with other AEAD \
+ * schemes which can't do this. \
+ */ \
+ \
+extern int pre##_eaxdecrypt(pre##_eaxctx */*ctx*/, \
+ const void */*src*/, size_t /*sz*/, \
+ buf */*dst*/); \
+ \
+/* --- @pre_eaxencryptdone@ --- * \
+ * \
+ * Arguments: @pre_eaxctx *ctx@ = pointer to an EAX context \
+ * @const pre_eaxaadctx *aad@ = pointer to AAD context, or \
+ * null \
+ * @buf *dst@ = buffer for remaining ciphertext \
+ * @void *tag@ = where to write the tag \
+ * @size_t tsz@ = length of tag to store \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Completes an EAX encryption operation. The @aad@ \
+ * pointer may be null if there is no additional \
+ * authenticated data. EAX doesn't buffer ciphertext, but \
+ * the output buffer is provided anyway for consistency \
+ * with other AEAD schemes which don't have this property; \
+ * the function will fail if the output buffer is broken. \
+ */ \
+ \
+extern int pre##_eaxencryptdone(pre##_eaxctx */*ctx*/, \
+ const pre##_eaxaadctx */*aad*/, \
+ buf */*dst*/, \
+ void */*tag*/, size_t /*tsz*/); \
+ \
+/* --- @pre_eaxdecryptdone@ --- * \
+ * \
+ * Arguments: @pre_eaxctx *ctx@ = pointer to an EAX context \
+ * @const pre_eaxaadctx *aad@ = pointer to AAD context, or \
+ * null \
+ * @buf *dst@ = buffer for remaining plaintext \
+ * @const void *tag@ = tag to verify \
+ * @size_t tsz@ = length of tag \
+ * \
+ * Returns: @+1@ for complete success; @0@ if tag verification \
+ * failed; @-1@ for other kinds of errors. \
+ * \
+ * Use: Completes an EAX decryption operation. The @aad@ \
+ * pointer may be null if there is no additional \
+ * authenticated data. EAX doesn't buffer plaintext, but \
+ * the output buffer is provided anyway for consistency \
+ * with other AEAD schemes which don't have this property; \
+ * the function will fail if the output buffer is broken. \
+ */ \
+ \
+extern int pre##_eaxdecryptdone(pre##_eaxctx */*ctx*/, \
+ const pre##_eaxaadctx */*aad*/, \
+ buf */*dst*/, \
+ const void */*tag*/, size_t /*tsz*/); \
+ \
+/* --- Generic AEAD interface --- */ \
+ \
+extern const gcaead pre##_eax;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
*/ \
\
void pre##_ecbsetkey(pre##_ecbctx *ctx, const pre##_ctx *k) \
-{ \
- ctx->ctx = *k; \
-} \
+ { ctx->ctx = *k; } \
\
/* --- @pre_ecbinit@ --- * \
* \
*/ \
\
void pre##_ecbinit(pre##_ecbctx *ctx, \
- const void *key, size_t sz, \
- const void *iv) \
-{ \
- pre##_init(&ctx->ctx, key, sz); \
-} \
+ const void *key, size_t sz, \
+ const void *iv) \
+ { pre##_init(&ctx->ctx, key, sz); } \
\
/* --- @pre_ecbencrypt@ --- * \
* \
*/ \
\
void pre##_ecbencrypt(pre##_ecbctx *ctx, \
- const void *src, void *dest, \
- size_t sz) \
+ const void *src, void *dest, \
+ size_t sz) \
{ \
const octet *s = src; \
octet *d = dest; \
+ uint32 t[PRE##_BLKSZ/4]; \
+ octet b[PRE##_BLKSZ]; \
+ octet y; \
+ unsigned i; \
\
- /* --- Empty blocks are trivial --- */ \
+ /* --- Empty blocks are trivial, and ECB is stateless --- */ \
\
- if (!sz) \
- return; \
+ if (!sz || !d) return; \
\
/* --- Short blocks aren't allowed in ECB --- * \
* \
* Hopefully... \
*/ \
\
- while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) { \
- uint32 x[PRE##_BLKSZ / 4]; \
- if (!s) \
- BLKC_ZERO(PRE, x); \
- else { \
- BLKC_LOAD(PRE, x, s); \
- s += PRE##_BLKSZ; \
- } \
- pre##_eblk(&ctx->ctx, x, x); \
- if (d) { \
- BLKC_STORE(PRE, d, x); \
- d += PRE##_BLKSZ; \
- } \
+ while (sz >= 2*PRE##_BLKSZ || sz == PRE##_BLKSZ) { \
+ if (!s) BLKC_ZERO(PRE, t); \
+ else { BLKC_LOAD(PRE, t, s); s += PRE##_BLKSZ; } \
+ pre##_eblk(&ctx->ctx, t, t); \
+ BLKC_STORE(PRE, d, t); d += PRE##_BLKSZ; \
sz -= PRE##_BLKSZ; \
} \
\
*/ \
\
if (sz) { \
- uint32 x[PRE##_BLKSZ / 4]; \
- octet b[PRE##_BLKSZ]; \
- unsigned i; \
\
/* --- Let @sz@ be the size of the partial block --- */ \
\
* out yet, because I've not read the partial plaintext block. \
*/ \
\
- if (!s) \
- BLKC_ZERO(PRE, x); \
- else { \
- BLKC_LOAD(PRE, x, s); \
- s += PRE##_BLKSZ; \
- } \
- pre##_eblk(&ctx->ctx, x, x); \
- BLKC_STORE(PRE, b, x); \
+ if (!s) BLKC_ZERO(PRE, t); \
+ else { BLKC_LOAD(PRE, t, s); s += PRE##_BLKSZ; } \
+ pre##_eblk(&ctx->ctx, t, t); \
+ BLKC_STORE(PRE, b, t); \
\
/* --- Second stage --- * \
* \
* ciphertext block. \
*/ \
\
- if (d) d += PRE##_BLKSZ; \
- for (i = 0; i < sz; i++) { \
- register octet y = b[i]; \
- b[i] = s[i]; \
- if (d) d[i] = y; \
- } \
- BLKC_LOAD(PRE, x, b); \
- pre##_eblk(&ctx->ctx, x, x); \
- if (d) BLKC_STORE(PRE, d - PRE##_BLKSZ, x); \
+ d += PRE##_BLKSZ; \
+ for (i = 0; i < sz; i++) { y = b[i]; b[i] = s[i]; d[i] = y; } \
+ BLKC_LOAD(PRE, t, b); \
+ pre##_eblk(&ctx->ctx, t, t); \
+ BLKC_STORE(PRE, d - PRE##_BLKSZ, t); \
} \
\
/* --- Done --- */ \
{ \
const octet *s = src; \
octet *d = dest; \
+ uint32 t[PRE##_BLKSZ/4]; \
+ octet b[PRE##_BLKSZ]; \
+ octet y; \
+ unsigned i; \
\
/* --- Empty blocks are trivial --- */ \
\
- if (!sz) \
- return; \
+ if (!sz) return; \
\
/* --- Short blocks aren't allowed in ECB --- * \
* \
* Each block is just handed to the block cipher in turn. \
*/ \
\
- while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) { \
- uint32 x[PRE##_BLKSZ / 4]; \
- BLKC_LOAD(PRE, x, s); \
- pre##_dblk(&ctx->ctx, x, x); \
- BLKC_STORE(PRE, d, x); \
- s += PRE##_BLKSZ; \
- d += PRE##_BLKSZ; \
+ while (sz >= 2*PRE##_BLKSZ || sz == PRE##_BLKSZ) { \
+ BLKC_LOAD(PRE, t, s); s += PRE##_BLKSZ; \
+ pre##_dblk(&ctx->ctx, t, t); \
+ BLKC_STORE(PRE, d, t); d += PRE##_BLKSZ; \
sz -= PRE##_BLKSZ; \
} \
\
*/ \
\
if (sz) { \
- uint32 x[PRE##_BLKSZ / 4]; \
- octet b[PRE##_BLKSZ]; \
- unsigned i; \
\
/* --- Let @sz@ be the size of the partial block --- */ \
\
* is carried over for the next encryption operation. \
*/ \
\
- BLKC_LOAD(PRE, x, s); \
- pre##_dblk(&ctx->ctx, x, x); \
- BLKC_STORE(PRE, b, x); \
+ BLKC_LOAD(PRE, t, s); \
+ pre##_dblk(&ctx->ctx, t, t); \
+ BLKC_STORE(PRE, b, t); \
\
/* --- Second stage --- * \
* \
\
s += PRE##_BLKSZ; \
d += PRE##_BLKSZ; \
- for (i = 0; i < sz; i++) { \
- register octet y = s[i]; \
- d[i] = b[i]; \
- b[i] = y; \
- } \
- BLKC_LOAD(PRE, x, b); \
- pre##_dblk(&ctx->ctx, x, x); \
- BLKC_STORE(PRE, d - PRE##_BLKSZ, x); \
+ for (i = 0; i < sz; i++) { y = s[i]; d[i] = b[i]; b[i] = y; } \
+ BLKC_LOAD(PRE, t, b); \
+ pre##_dblk(&ctx->ctx, t, t); \
+ BLKC_STORE(PRE, d - PRE##_BLKSZ, t); \
} \
\
/* --- Done --- */ \
} \
\
static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) \
-{ \
- gctx *g = (gctx *)c; \
- pre##_ecbencrypt(&g->k, s, t, sz); \
-} \
+ { gctx *g = (gctx *)c; pre##_ecbencrypt(&g->k, s, t, sz); } \
\
static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz) \
-{ \
- gctx *g = (gctx *)c; \
- pre##_ecbdecrypt(&g->k, s, t, sz); \
-} \
+ { gctx *g = (gctx *)c; pre##_ecbdecrypt(&g->k, s, t, sz); } \
\
static void gdestroy(gcipher *c) \
-{ \
- gctx *g = (gctx *)c; \
- BURN(*g); \
- S_DESTROY(g); \
-} \
+ { gctx *g = (gctx *)c; BURN(*g); S_DESTROY(g); } \
\
static const gcipher_ops gops = { \
&pre##_ecb, \
#ifdef TEST_RIG
-#include <stdio.h>
-
-#include "daftstory.h"
+#include "modes-test.h"
/* --- @ECB_TEST@ --- *
*
#define ECB_TESTX(PRE, pre, name, fname) \
\
-/* --- Initial plaintext for the test --- */ \
- \
-static const octet text[] = TEXT; \
+static pre##_ctx key; \
+static pre##_ecbctx ctx; \
\
-/* --- Key and IV to use --- */ \
+static void pre##_ecb_test_setup(const octet *k, size_t ksz) \
+ { pre##_init(&key, k, ksz); pre##_ecbsetkey(&ctx, &key); } \
\
-static const octet key[] = KEY; \
-static const octet iv[] = IV; \
+static void pre##_ecb_test_reset(const octet *iv) \
+ { ; } \
\
-/* --- Buffers for encryption and decryption output --- */ \
+static void pre##_ecb_test_enc(const octet *s, octet *d, size_t sz) \
+ { pre##_ecbencrypt(&ctx, s, d, sz); } \
\
-static octet ct[sizeof(text)]; \
-static octet pt[sizeof(text)]; \
+static void pre##_ecb_test_dec(const octet *s, octet *d, size_t sz) \
+ { pre##_ecbdecrypt(&ctx, s, d, sz); } \
\
-static void hexdump(const octet *p, size_t sz, size_t off) \
+int main(int argc, char *argv[]) \
{ \
- const octet *q = p + sz; \
- for (sz = 0; p < q; p++, sz++) { \
- printf("%02x", *p); \
- if ((off + sz + 1) % PRE##_BLKSZ == 0) \
- putchar(':'); \
- } \
-} \
- \
-int main(void) \
-{ \
- size_t sz = 0, rest; \
- pre##_ecbctx ctx; \
- int status = 0; \
- int done = 0; \
- \
- size_t keysz = PRE##_KEYSZ ? \
- PRE##_KEYSZ : strlen((const char *)key); \
- \
- fputs(name "-ecb: ", stdout); \
- \
- pre##_ecbinit(&ctx, key, keysz, iv); \
- \
- while (sz <= sizeof(text)) { \
- rest = sizeof(text) - sz; \
- if ((sz != 0 && sz < PRE##_BLKSZ) || \
- (rest != 0 && rest < PRE##_BLKSZ)) \
- goto next; \
- memcpy(ct, text, sizeof(text)); \
- pre##_ecbencrypt(&ctx, ct, ct, sz); \
- pre##_ecbencrypt(&ctx, ct + sz, ct + sz, rest); \
- memcpy(pt, ct, sizeof(text)); \
- pre##_ecbdecrypt(&ctx, pt, pt, sz); \
- pre##_ecbdecrypt(&ctx, pt + sz, pt + sz, rest); \
- if (memcmp(pt, text, sizeof(text)) == 0) { \
- done++; \
- if (sizeof(text) < 40 || done % 8 == 0) \
- fputc('.', stdout); \
- if (done % 480 == 0) \
- fputs("\n\t", stdout); \
- fflush(stdout); \
- } else { \
- printf("\nError (sz = %lu)\n", (unsigned long)sz); \
- status = 1; \
- printf("\tplaintext = "); hexdump(text, sz, 0); \
- printf(", "); hexdump(text + sz, rest, sz); \
- fputc('\n', stdout); \
- printf("\tciphertext = "); hexdump(ct, sz, 0); \
- printf(", "); hexdump(ct + sz, rest, sz); \
- fputc('\n', stdout); \
- printf("\trecovered text = "); hexdump(pt, sz, 0); \
- printf(", "); hexdump(pt + sz, rest, sz); \
- fputc('\n', stdout); \
- fputc('\n', stdout); \
- } \
- next: \
- if (sz < 63) \
- sz++; \
- else \
- sz += 9; \
- } \
- \
- fputs(status ? " failed\n" : " ok\n", stdout); \
- return (status); \
+ return test_encmode(fname "-ecb", PRE##_KEYSZ, PRE##_BLKSZ, \
+ PRE##_BLKSZ, TEMF_REFALIGN, \
+ pre##_ecb_test_setup, pre##_ecb_test_reset, \
+ pre##_ecb_test_enc, pre##_ecb_test_dec, \
+ argc, argv); \
}
#else
--- /dev/null
+/* -*-c-*-
+ *
+ * Generic authenticated encryption interface
+ *
+ * (c) 2018 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "gaead.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @gaead_encrypt@ --- *
+ *
+ * Arguments: @const gaead_key *k@ = the AEAD key, already prepared
+ * @const void *n@, @size_t nsz@ = nonce
+ * @const void *h@, @size_t hsz@ = additional `header' data
+ * @const void *m@, @size_t msz@ = message input
+ * @void *c@, @size_t *csz_input@ = ciphertext output
+ * @void *t@, @size_t tsz@ = tag output
+ *
+ * Returns: Zero on success, @-1@ if the output buffer is too small.
+ *
+ * Use: Encrypts and authenticates a message in a single operation.
+ * This just saves a bunch of messing about with the various
+ * @gaead_...@ objects.
+ *
+ * On entry, @*csz_inout@ should be the capacity of the
+ * ciphertext buffer; on exit, it will be updated with the
+ * actual size of ciphertext produced. The function will not
+ * fail if @*csz_inout >= msz + k->c->ohd@.
+ */
+
+int gaead_encrypt(const gaead_key *k, const void *n, size_t nsz,
+ const void *h, size_t hsz,
+ const void *m, size_t msz,
+ void *c, size_t *csz_inout,
+ void *t, size_t tsz)
+{
+ gaead_enc *e = 0;
+ gaead_aad *a = 0;
+ buf b;
+ int rc;
+
+ buf_init(&b, c, *csz_inout);
+ e = GAEAD_ENC(k, n, nsz, hsz, msz, tsz); if (!e) { rc = -1; goto end; }
+ if (hsz) { a = GAEAD_AAD(e); GAEAD_HASH(a, h, hsz); }
+ rc = GAEAD_ENCRYPT(e, m, msz, &b); if (rc) goto end;
+ rc = GAEAD_DONE(e, a, &b, t, tsz);
+end:
+ if (rc >= 0) *csz_inout = BLEN(&b);
+ if (e) GAEAD_DESTROY(e);
+ if (a) GAEAD_DESTROY(a);
+ return (rc);
+}
+
+/* --- @gaead_decrypt@ --- *
+ *
+ * Arguments: @const gaead_key *k@ = the AEAD key, already prepared
+ * @const void *n@, @size_t nsz@ = nonce
+ * @const void *h@, @size_t hsz@ = additional `header' data
+ * @const void *c@, @size_t csz@ = ciphertext input
+ * @void *m@, @size_t *msz_inout@ = message output
+ * @const void *t@, @size_t tsz@ = tag input
+ *
+ * Returns: @+1@ if everything is good; zero for authentication failure,
+ * @-1@ for other problems.
+ *
+ * Use: Decrypts and verifies a message in a single operation.
+ * This just saves a bunch of messing about with the various
+ * @gaead_...@ objects.
+ *
+ * On entry, @*msz_inout@ should be the capacity of the
+ * message buffer; on exit, it will be updated with the
+ * actual size of message produced. The function will not
+ * fail if @*msz_inout >= csz@.
+ */
+
+int gaead_decrypt(const gaead_key *k, const void *n, size_t nsz,
+ const void *h, size_t hsz,
+ const void *c, size_t csz,
+ void *m, size_t *msz_inout,
+ const void *t, size_t tsz)
+{
+ gaead_dec *d = 0;
+ gaead_aad *a = 0;
+ buf b;
+ int rc;
+
+ buf_init(&b, m, *msz_inout);
+ d = GAEAD_DEC(k, n, nsz, hsz, csz, tsz); if (!d) { rc = -1; goto end; }
+ if (hsz) { a = GAEAD_AAD(d); GAEAD_HASH(a, h, hsz); }
+ rc = GAEAD_DECRYPT(d, c, csz, &b); if (rc) goto end;
+ rc = GAEAD_DONE(d, a, &b, t, tsz);
+end:
+ if (rc >= 0) *msz_inout = BLEN(&b);
+ if (d) GAEAD_DESTROY(d);
+ if (a) GAEAD_DESTROY(a);
+ return (rc);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
--- /dev/null
+/* -*-c-*-
+ *
+ * Generic authenticated encryption interface
+ *
+ * (c) 2018 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef CATACOMB_GAEAD_H
+#define CATACOMB_GAEAD_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_BUF_H
+# include "buf.h"
+#endif
+
+#ifndef CATACOMB_KEYSZ_H
+# include "keysz.h"
+#endif
+
+/*----- Generic AEAD interface --------------------------------------------*/
+
+typedef struct gaead_key {
+ const struct gaead_keyops *ops;
+} gaead_key;
+
+typedef struct gaead_enc {
+ const struct gaead_encops *ops;
+} gaead_enc;
+
+typedef struct gaead_dec {
+ const struct gaead_decops *ops;
+} gaead_dec;
+
+typedef struct gaead_aad {
+ const struct gaead_aadops *ops;
+} gaead_aad;
+
+typedef struct gaead_keyops {
+ const struct gcaead *c; /* Pointer to AEAD class */
+
+ gaead_aad *(*aad)(const gaead_key */*k*/);
+ /* Return an AAD-hashing object for this key. Only available if
+ * the @AEADF_AADNDEP@ class flag is clear.
+ */
+
+ gaead_enc *(*enc)(const gaead_key */*k*/,
+ const void */*n*/, size_t /*nsz*/,
+ size_t /*hsz*/, size_t /*msz*/, size_t /*tsz*/);
+ /* Return a message encryption object for this key, with the given
+ * nonce. If the @AEADF_PCHSZ@, @AEADF_PCMSZ@ and/or @AEADF_PCTSZ@
+ * class flags are set then the caller must provide the AAD length
+ * @hsz@, message length @msz@ and/or tag length @tsz@ respectively;
+ * otherwise these arguments will be ignored.
+ *
+ * The caller is expected to have ensured that the nonce and tag
+ * lengths are acceptable, e.g., by checking against the tables
+ * provided in the class object. Some unfortunate AEAD schemes have
+ * more complicated requirements: if the sizes are unacceptable in
+ * combination, this function returns null.
+ */
+
+ gaead_dec *(*dec)(const gaead_key */*k*/,
+ const void */*n*/, size_t /*nsz*/,
+ size_t /*hsz*/, size_t /*csz*/, size_t /*tsz*/);
+ /* Return a message encryption object for this key, with the given
+ * nonce. If the @AEADF_PCHSZ@, @AEADF_PCMSZ@ and/or @AEADF_PCTSZ@
+ * class flags are set then the caller must provide the AAD length
+ * @hsz@, ciphertext length @csz@ and/or tag length @tsz@
+ * respectively; otherwise these arguments will be ignored.
+ *
+ * The caller is expected to have ensured that the nonce and tag
+ * lengths are acceptable, e.g., by checking against the tables
+ * provided in the class object. Some unfortunate AEAD schemes have
+ * more complicated requirements: if the sizes are unacceptable in
+ * combination, this function returns null.
+ */
+
+ void (*destroy)(gaead_key */*k*/);
+ /* Destroy the key object. This will not invalidate AAD-hashing,
+ * encryption or decryption objects.
+ */
+
+} gaead_keyops;
+
+typedef struct gaead_aadops {
+ const struct gcaead *c; /* Pointer to AEAD class */
+
+ gaead_aad *(*dup)(const gaead_aad */*a*/);
+ /* Return a new AAD-hashing object with a copy of this object's
+ * state. This is useful if the AAD for multiple messages shares a
+ * common prefix: the prefix can be processed once, and a copy
+ * created for each different suffix. Only available if the
+ * @AEADF_AADNDEP@ class flag is clear.
+ */
+
+ void (*hash)(gaead_aad */*a*/, const void */*h*/, size_t /*hsz*/);
+ /* Feed header (additional authenticated) data into the AAD-hashing
+ * object. If the @AEADF_NOAAD@ class flag is set then @hsz@ must be
+ * zero.
+ */
+
+ void (*destroy)(gaead_aad */*a*/);
+ /* Destroy the AAD-hashing object. */
+
+} gaead_aadops;
+
+typedef struct gaead_encops {
+ const struct gcaead *c; /* Pointer to AEAD class */
+
+ gaead_aad *(*aad)(gaead_enc */*e*/);
+ /* Return a new AAD-hashing object for the current key and nonce. If
+ * the @AEADF_AADNDEP@ class flag is clear then this works just as if
+ * the @aad@ method on the key had been called instead: the new
+ * object is in fact independent of the nonce and can be used with
+ * any encryption or decryption operation. If @AEADF_AADNDEP@ is
+ * set, then the returned AAD-hashing object is specific to this
+ * encryption operation. If @AEADF_AADFIRST@ is also set, then all
+ * additional data must be hashed before any message data is
+ * presented for encryption.
+ */
+
+ int (*reinit)(gaead_enc */*e*/, const void */*n*/, size_t /*nsz*/,
+ size_t /*hsz*/, size_t /*msz*/, size_t /*tsz*/);
+ /* Reinitialize this object for a new encryption operation with a
+ * different nonce. The data lengths @hsz@, @msz@, and @tsz@ are as
+ * for the key @enc@ method. Returns zero on success.
+ *
+ * The caller is expected to have ensured that the nonce and tag
+ * lengths are acceptable, e.g., by checking against the tables
+ * provided in the class object. Some unfortunate AEAD schemes have
+ * more complicated requirements: if the sizes are unacceptable in
+ * combination, this function returns @-1@.
+ */
+
+ int (*encrypt)(gaead_enc */*e*/, const void */*m*/, size_t /*msz*/,
+ buf */*b*/);
+ /* Encrypt a chunk of data, writing the result to the output buffer
+ * @b@. This will succeed if @BLEFT(b) >= msz + e->c->bufsz@;
+ * otherwise it might fail. Failure doesn't affect the encryption
+ * operation's state. Returns zero on success, or @-1@ on failure.
+ */
+
+ int (*done)(gaead_enc */*e*/, const gaead_aad */*a*/, buf */*b*/,
+ void */*t*/, size_t /*tsz*/);
+ /* Completes encryption, returning the authentication tag for the
+ * message and any additional authenticated data accumulated in @a@.
+ * The pointer @a@ may be null if there is no AAD. If the
+ * @AEADF_AADNDEP@ class flag is set, and any header data has been
+ * provided to the operation's AAD-hashing object, then a pointer to
+ * this object must be provided as @a@. If @AEADF_AADNDEP@ is clear,
+ * then any AAD-hashing object for this key may be provided.
+ * Internally buffered ciphertext may be written to @b@. This will
+ * succeed if @BLEFT(b) >= e->c->bufsz@; otherwise it might fail.
+ * Failure doesn't affect the encryption operation's state. Returns
+ * zero on success, or @-1@ on failure.
+ */
+
+ void (*destroy)(gaead_enc */*e*/);
+ /* Destroy the encryption object. */
+
+} gaead_encops;
+
+typedef struct gaead_decops {
+ const struct gcaead *c; /* Pointer to AEAD class */
+
+ gaead_aad *(*aad)(gaead_dec */*d*/);
+ /* Return a new AAD-hashing object for the current key and nonce. If
+ * the @AEADF_AADNDEP@ class flag is clear then this works just as if
+ * the @aad@ method on the key had been called instead: the new
+ * object is in fact independent of the nonce and can be used with
+ * any encryption or decryption operation. If @AEADF_AADNDEP@ is
+ * set, then the returned AAD-hashing object is specific to this
+ * decryption operation. If @AEADF_AADFIRST@ is also set, then all
+ * additional data must be hashed before any ciphertext is presented
+ * for decryption.
+ */
+
+ int (*reinit)(gaead_dec */*d*/, const void */*n*/, size_t /*nsz*/,
+ size_t /*hsz*/, size_t /*csz*/, size_t /*tsz*/);
+ /* Reinitialize this object for a new decryption operation with a
+ * different nonce. The data lengths @hsz@, @csz@, and @tsz@ are as
+ * for the key @dec@ method.
+ *
+ * The caller is expected to have ensured that the nonce and tag
+ * lengths are acceptable, e.g., by checking against the tables
+ * provided in the class object. Some unfortunate AEAD schemes have
+ * more complicated requirements: if the sizes are unacceptable in
+ * combination, this function returns @-1@.
+ */
+
+ int (*decrypt)(gaead_dec */*d*/, const void */*c*/, size_t /*csz*/,
+ buf */*b*/);
+ /* Decrypt a chunk of data, writing the result to the output buffer
+ * @b@. This will succeed if @BLEFT(b) >= msz + e->c->bufsz@;
+ * otherwise it might fail. Failure doesn't affect the decryption
+ * operation's state. Returns zero on success, or @-1@ on failure.
+ *
+ * CAUTION: the decrypted data may be inauthentic. Don't do anything
+ * risky with it until its tag has been verified.
+ */
+
+ int (*done)(gaead_dec */*d*/, const gaead_aad */*a*/, buf */*b*/,
+ const void */*t*/, size_t /*tsz*/);
+ /* Completes decryption, verifying the authentication tag for the
+ * message and any additional authenticated data accumulated in @a@.
+ * The pointer @a@ may be null if there is no AAD. If the
+ * @AEADF_AADNDEP@ class flag is set, and any header data has been
+ * provided to the operation's AAD-hashing object, then a pointer to
+ * this object must be provided as @a@. If @AEADF_AADNDEP@ is clear,
+ * then any AAD-hashing object for this key may be provided.
+ * Internally buffered plaintext may be written to @b@. This will
+ * succeed if @BLEFT(b) >= e->c->bufsz@; otherwise it might fail.
+ * Failure doesn't affect the decryption operation's state. Returns
+ * @+1@ on success, @0@ on verification failure, or @-1@ on other
+ * kinds of failures.
+ */
+
+ void (*destroy)(gaead_dec */*d*/);
+ /* Destroy the decryption object. */
+
+} gaead_decops;
+
+typedef struct gcaead {
+ const char *name; /* AEAD scheme name */
+ const octet *keysz; /* Acceptable keys-size table */
+ const octet *noncesz; /* Acceptable nonce-size table */
+ const octet *tagsz; /* Acceptable tag-size table */
+ size_t blksz; /* Block size, or zero if none */
+ unsigned bufsz; /* Maximum extra msg/ct output */
+ unsigned ohd; /* Maximum encryption overhead */
+ unsigned f; /* Various other flags */
+#define AEADF_PCHSZ 1u /* Precommit to AAD size */
+#define AEADF_PCMSZ 2u /* Precommit to message size */
+#define AEADF_PCTSZ 4u /* Precommit to tag size */
+#define AEADF_AADNDEP 8u /* AAD hash is nonce-dependent */
+#define AEADF_AADFIRST 16u /* AAD must precede msg/ct */
+#define AEADF_NOAAD 32u /* AAD is not permitted */
+
+ gaead_key *(*key)(const void */*k*/, size_t /*ksz*/);
+ /* Return a key object (above) with the given key material. */
+
+ int (*szok)(size_t /*nsz*/, size_t /*hsz*/,
+ size_t /*msz*/, size_t /*tsz*/);
+ /* Return true (nonzero) if the given collection of sizes for nonce,
+ * header, message, and tag are acceptable in combination. Mostly
+ * this will be true if the nonce length and tag size are are
+ * acceptable independently (and the header and message lengths are
+ * irrelevant), but some schemes are more awkward.
+ */
+} gcaead;
+
+#define GAEAD_KEY(cc, k, ksz) (cc)->key((k), (ksz))
+#define GAEAD_CLASS(obj) (obj)->ops->c
+#define GAEAD_AAD(ked) (ked)->ops->aad((ked))
+#define GAEAD_REINIT(ed, n, nsz, hsz, msz, tsz) \
+ (ed)->ops->reinit((ed), (n), (nsz), (hsz), (msz), (tsz))
+#define GAEAD_ENC(k, n, nsz, hsz, msz, tsz) \
+ (k)->ops->enc((k), (n), (nsz), (hsz), (msz), (tsz))
+#define GAEAD_DEC(k, n, nsz, hsz, msz, tsz) \
+ (k)->ops->dec((k), (n), (nsz), (hsz), (msz), (tsz))
+#define GAEAD_DUP(a) (a)->ops->dup((a))
+#define GAEAD_HASH(a, h, hsz) (a)->ops->hash((a), (h), (hsz))
+#define GAEAD_ENCRYPT(e, m, msz, b) \
+ (e)->ops->encrypt((e), (m), (msz), (b))
+#define GAEAD_DECRYPT(d, c, csz, b) \
+ (d)->ops->decrypt((d), (c), (csz), (b))
+#define GAEAD_DONE(ed, aad, b, t, tsz) \
+ (ed)->ops->done((ed), (aad), (b), (t), (tsz))
+#define GAEAD_DESTROY(obj) (obj)->ops->destroy((obj))
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @gaead_szokcommon@ --- *
+ *
+ * Arguments: @const gcaead *aec@ = pointer to AEAD class
+ * @size_t nsz@, @size_t hsz@, @size_t msz@, @size_t tsz@ =
+ * nonce, header, message, and tag sizes
+ *
+ * Returns: Nonzero if the sizes are acceptable to the AEAD scheme in
+ * combination.
+ *
+ * Use: Generic implementation for sensible AEAD schemes.
+ */
+
+extern int gaead_szokcommon(const gcaead */*aec*/,
+ size_t /*nsz*/, size_t /*hsz*/,
+ size_t /*msz*/, size_t /*tsz*/);
+
+/* --- @gaead_encrypt@ --- *
+ *
+ * Arguments: @const gaead_key *k@ = the AEAD key, already prepared
+ * @const void *n@, @size_t nsz@ = nonce
+ * @const void *h@, @size_t hsz@ = additional `header' data
+ * @const void *m@, @size_t msz@ = message input
+ * @void *c@, @size_t *csz_input@ = ciphertext output
+ * @void *t@, @size_t tsz@ = tag output
+ *
+ * Returns: Zero on success, @-1@ if the output buffer is too small.
+ *
+ * Use: Encrypts and authenticates a message in a single operation.
+ * This just saves a bunch of messing about with the various
+ * @gaead_...@ objects.
+ *
+ * On entry, @*csz_inout@ should be the capacity of the
+ * ciphertext buffer; on exit, it will be updated with the
+ * actual size of ciphertext produced. The function will not
+ * fail if @*csz_inout >= msz + k->c->ohd@.
+ */
+
+extern int gaead_encrypt(const gaead_key */*k*/,
+ const void */*n*/, size_t /*nsz*/,
+ const void */*h*/, size_t /*hsz*/,
+ const void */*m*/, size_t /*msz*/,
+ void */*c*/, size_t */*csz_inout*/,
+ void */*t*/, size_t /*tsz*/);
+
+/* --- @gaead_decrypt@ --- *
+ *
+ * Arguments: @const gaead_key *k@ = the AEAD key, already prepared
+ * @const void *n@, @size_t nsz@ = nonce
+ * @const void *h@, @size_t hsz@ = additional `header' data
+ * @const void *c@, @size_t csz@ = ciphertext input
+ * @void *m@, @size_t *msz_inout@ = message output
+ * @const void *t@, @size_t tsz@ = tag input
+ *
+ * Returns: @+1@ if everything is good; zero for authentication failure,
+ * @-1@ for other problems.
+ *
+ * Use: Decrypts and verifies a message in a single operation.
+ * This just saves a bunch of messing about with the various
+ * @gaead_...@ objects.
+ *
+ * On entry, @*msz_inout@ should be the capacity of the
+ * message buffer; on exit, it will be updated with the
+ * actual size of message produced. The function will not
+ * fail if @*msz_inout >= csz@.
+ */
+
+extern int gaead_decrypt(const gaead_key */*k*/,
+ const void */*n*/, size_t /*nsz*/,
+ const void */*h*/, size_t /*hsz*/,
+ const void */*c*/, size_t /*csz*/,
+ void */*m*/, size_t */*msz_inout*/,
+ const void */*t*/, size_t /*tsz*/);
+
+/*----- Tables ------------------------------------------------------------*/
+
+extern const gcaead *const gaeadtab[];
+
+/* --- @gaead_byname@ --- *
+ *
+ * Arguments: @const char *p@ = pointer to name string
+ *
+ * Returns: The named AEAD class, or null.
+ */
+
+extern const gcaead *gaead_byname(const char */*p*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
--- /dev/null
+/// -*- mode: asm; asm-comment-char: ?/ -*-
+///
+/// GCM acceleration for ARM processors
+///
+/// (c) 2019 Straylight/Edgeware
+///
+
+///----- Licensing notice ---------------------------------------------------
+///
+/// This file is part of Catacomb.
+///
+/// Catacomb is free software: you can redistribute it and/or modify it
+/// under the terms of the GNU Library General Public License as published
+/// by the Free Software Foundation; either version 2 of the License, or
+/// (at your option) any later version.
+///
+/// Catacomb is distributed in the hope that it will be useful, but
+/// WITHOUT ANY WARRANTY; without even the implied warranty of
+/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+/// Library General Public License for more details.
+///
+/// You should have received a copy of the GNU Library General Public
+/// License along with Catacomb. If not, write to the Free Software
+/// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+/// USA.
+
+///--------------------------------------------------------------------------
+/// Preliminaries.
+
+#include "config.h"
+#include "asm-common.h"
+
+ .arch armv8-a
+ .fpu crypto-neon-fp-armv8
+
+ .text
+
+///--------------------------------------------------------------------------
+/// Multiplication macros.
+
+ // The good news is that we have a fancy instruction to do the
+ // multiplications. The bad news is that it's not particularly well-
+ // suited to the job.
+ //
+ // For one thing, it only does a 64-bit multiplication, so in general
+ // we'll need to synthesize the full-width multiply by hand. For
+ // another thing, it doesn't help with the reduction, so we have to
+ // do that by hand too. And, finally, GCM has crazy bit ordering,
+ // and the instruction does nothing useful for that at all.
+ //
+ // Focusing on that last problem first: the bits aren't in monotonic
+ // significance order unless we permute them. If we reverse the byte
+ // order, then we'll have the bits in monotonic order, but backwards,
+ // so the degree-0 coefficient will be in the most-significant bit.
+ //
+ // This is less of a difficulty than it seems at first, because
+ // algebra. Suppose we are given u = SUM_{0<=i<n} u_i t^i and v =
+ // SUM_{0<=j<n} v_j t^j; then
+ //
+ // u v = SUM_{0<=i,j<n} u_i v_j t^{i+j}
+ //
+ // Suppose instead that we're given ũ = SUM_{0<=i<n} u_{n-i-1} t^i
+ // and ṽ = SUM_{0<=j<n} v_{n-j-1} t^j, so the bits are backwards.
+ // Then
+ //
+ // ũ ṽ = SUM_{0<=i,j<n} u_{n-i-1} v_{n-j-1} t^{i+j}
+ // = SUM_{0<=i,j<n} u_i v_j t^{2n-2-(i+j)}
+ //
+ // which is almost the bit-reversal of u v, only it's shifted right
+ // by one place. Oh, well: we'll have to shift it back later.
+ //
+ // That was important to think about, but there's not a great deal to
+ // do about it yet other than to convert what we've got from the
+ // blockcipher's byte-ordering convention to our big-endian
+ // convention. Since this depends on the blockcipher convention,
+ // we'll leave the caller to cope with this: the macros here will
+ // assume that the operands are in `register' format, which is the
+ // same as the external representation, except that the bytes within
+ // each 64-bit piece are reversed. In the commentary, pieces of
+ // polynomial are numbered according to the degree of the
+ // coefficients, so the unit coefficient of some polynomial a is in
+ // a_0.
+ //
+ // The commentary for `mul128' is the most detailed. The other
+ // macros assume that you've already read and understood that.
+
+.macro mul128
+ // Enter with u and v in q0 and q1 respectively; leave with z = u v
+ // in q0. Clobbers q1--q3, q8, q9.
+
+ // First for the double-precision multiplication. It's tempting to
+ // use Karatsuba's identity here, but I suspect that loses more in
+ // the shifting, bit-twiddling, and dependency chains that it gains
+ // in saving a multiplication which otherwise pipelines well.
+ // q0 = // (u_0; u_1)
+ // q1 = // (v_0; v_1)
+ vmull.p64 q2, d1, d2 // u_1 v_0
+ vmull.p64 q3, d0, d3 // u_0 v_1
+ vmull.p64 q8, d1, d3 // (x_3; t_1) = u_1 v_1
+ vmull.p64 q9, d0, d2 // (t_0; x_0) = u_0 v_0
+
+ // Arrange the pieces to form a double-precision polynomial.
+ veor q2, q2, q3 // (m_1; m_0) = u_0 v_1 + u_1 v_0
+ veor d17, d17, d4 // x_2 = t_1 + m_1
+ veor d18, d18, d5 // x_1 = t_0 + m_0
+ // q8 = // (x_3; x_2)
+ // q9 = // (x_1; x_0)
+
+ // Two-and-a-half problems remain. The first is that this product is
+ // shifted left by one place, which is annoying. Let's take care of
+ // that now. Once this is done, we'll be properly in GCM's backwards
+ // bit-ordering.
+ //
+ // The half a problem is that the result wants to have its 64-bit
+ // halves switched. Here turns out to be the best place to arrange
+ // for that.
+ //
+ // q9 q8
+ // ,-------------.-------------. ,-------------.-------------.
+ // | 0 x_0-x_62 | x_63-x_126 | | x_127-x_190 | x_191-x_254 |
+ // `-------------^-------------' `-------------^-------------'
+ // d19 d18 d17 d16
+ //
+ // We start by shifting each 32-bit lane right (from GCM's point of
+ // view -- physically, left) by one place, which gives us this:
+ //
+ // low (q9) high (q8)
+ // ,-------------.-------------. ,-------------.-------------.
+ // | x_0-x_62 0 |x_64-x_126 0 | |x_128-x_190 0|x_192-x_254 0|
+ // `-------------^-------------' `-------------^-------------'
+ // d19 d18 d17 d16
+ //
+ // but we've lost a bunch of bits. We separately shift each lane
+ // left by 31 places to give us the bits we lost.
+ //
+ // low (q3) high (q2)
+ // ,-------------.-------------. ,-------------.-------------.
+ // | 0...0 | 0...0 x_63 | | 0...0 x_127 | 0...0 x_191 |
+ // `-------------^-------------' `-------------^-------------'
+ // d6 d5 d4
+ //
+ // Since we can address each of these pieces individually, putting
+ // them together is relatively straightforward.
+
+
+ vshr.u64 d6, d18, #63 // shifted left; just the carries
+ vshl.u64 q9, q9, #1 // shifted right, but dropped carries
+ vshr.u64 q2, q8, #63
+ vshl.u64 q8, q8, #1
+ vorr d0, d19, d6 // y_0
+ vorr d1, d18, d5 // y_1
+ vorr d2, d17, d4 // y_2
+ vmov d3, d16 // y_3
+
+ // And the other one is that the result needs to be reduced modulo
+ // p(t) = t^128 + t^7 + t^2 + t + 1. Let R = t^128 = t^7 + t^2 + t +
+ // 1 in our field. So far, we've calculated z_0 and z_1 such that
+ // z_0 + z_1 R = u v using the identity R = t^128: now we must
+ // collapse the two halves of y together using the other identity R =
+ // t^7 + t^2 + t + 1.
+ //
+ // We do this by working on y_2 and y_3 separately, so consider y_i
+ // for i = 2 or 3. Certainly, y_i t^{64i} = y_i R t^{64(i-2) =
+ // (t^7 + t^2 + t + 1) y_i t^{64(i-2)}, but we can't use that
+ // directly without breaking up the 64-bit word structure. Instead,
+ // we start by considering just y_i t^7 t^{64(i-2)}, which again
+ // looks tricky. Now, split y_i = a_i + t^57 b_i, with deg a_i < 57;
+ // then
+ //
+ // y_i t^7 t^{64(i-2)} = a_i t^7 t^{64(i-2)} + b_i t^{64(i-1)}
+ //
+ // We can similarly decompose y_i t^2 and y_i t into a pair of 64-bit
+ // contributions to the t^{64(i-2)} and t^{64(i-1)} words, but the
+ // splits are different. This is lovely, with one small snag: when
+ // we do this to y_3, we end up with a contribution back into the
+ // t^128 coefficient word. But notice that only the low seven bits
+ // of this word are affected, so there's no knock-on contribution
+ // into the t^64 word. Therefore, if we handle the high bits of each
+ // word together, and then the low bits, everything will be fine.
+
+ // First, shift the high bits down.
+ vshl.u64 q2, q1, #63 // the b_i for t
+ vshl.u64 q3, q1, #62 // the b_i for t^2
+ vshl.u64 q8, q1, #57 // the b_i for t^7
+ veor q2, q2, q3 // add them all together
+ veor q2, q2, q8
+ veor d2, d2, d5 // contribution into low half
+ veor d1, d1, d4 // and high half
+
+ // And then shift the low bits up.
+ vshr.u64 q2, q1, #1
+ vshr.u64 q3, q1, #2
+ vshr.u64 q8, q1, #7
+ veor q0, q0, q1 // mix in the unit contribution
+ veor q2, q2, q3 // t and t^2 contribs
+ veor q0, q0, q8 // low, unit, and t^7 contribs
+ veor q0, q0, q2 // mix them together and we're done
+.endm
+
+.macro mul64
+ // Enter with u and v in the low halves of d0 and d1 respectively;
+ // leave with z = u v in d0. Clobbers d1--d5.
+
+ // The multiplication is thankfully easy.
+ vmull.p64 q0, d0, d1 // u v
+
+ // Shift the product up by one place, and swap the two halves. After
+ // this, we're in GCM bizarro-world.
+ vshr.u64 d2, d0, #63 // shifted left; just the carries
+ vshl.u64 d3, d1, #1 // low half right
+ vshl.u64 d1, d0, #1 // high half shifted right
+ vorr d0, d3, d2 // mix in the carries
+
+ // Now we must reduce. This is essentially the same as the 128-bit
+ // case above, but mostly simpler because everything is smaller. The
+ // polynomial this time is p(t) = t^64 + t^4 + t^3 + t + 1.
+
+ // First, shift the high bits down.
+ vshl.u64 d2, d1, #63 // b_i for t
+ vshl.u64 d3, d1, #61 // b_i for t^3
+ vshl.u64 d4, d1, #60 // b_i for t^4
+ veor d2, d2, d3 // add them all together
+ veor d2, d2, d4
+ veor d1, d1, d2 // contribution back into high half
+
+ // And then shift the low bits up.
+ vshr.u64 d2, d1, #1
+ vshr.u64 d3, d1, #3
+ vshr.u64 d4, d1, #4
+ veor d0, d0, d1 // mix in the unit contribution
+ veor d2, d2, d3 // t and t^3 contribs
+ veor d0, d0, d4 // low, unit, and t^4
+ veor d0, d0, d2 // mix them together and we're done
+.endm
+
+.macro mul96
+ // Enter with u and v in the most-significant three words of q0 and
+ // q1 respectively, and zero in the low words, and zero in q15; leave
+ // with z = u v in the high three words of q0, and /junk/ in the low
+ // word. Clobbers ???.
+
+ // This is an inconvenient size. There's nothing for it but to do
+ // four multiplications, as if for the 128-bit case. It's possible
+ // that there's cruft in the top 32 bits of the input registers, so
+ // shift both of them up by four bytes before we start. This will
+ // mean that the high 64 bits of the result (from GCM's viewpoint)
+ // will be zero.
+ // q0 = // (u_0 + u_1 t^32; u_2)
+ // q1 = // (v_0 + v_1 t^32; v_2)
+ vmull.p64 q8, d1, d2 // u_2 (v_0 + v_1 t^32) = e_0
+ vmull.p64 q9, d0, d3 // v_2 (u_0 + u_1 t^32) = e_1
+ vmull.p64 q3, d1, d3 // u_2 v_2 t^64 = d = (0; d)
+ vmull.p64 q0, d0, d2 // u_0 v_0 + (u_0 v_1 + u_1 v_0) t^32
+ // + u_1 v_1 t^64 = f
+
+ // Extract the high and low halves of the 192-bit result. The answer
+ // we want is d t^128 + e t^64 + f, where e = e_0 + e_1. The low 96
+ // bits of the answer will end up in q0, and the high 96 bits will
+ // end up in q1; we'll need both of these to have zero in their
+ // bottom 32 bits.
+ //
+ // Here, bot(x) is the low 96 bits of a 192-bit quantity x, arranged
+ // in the low 96 bits of a SIMD register, with junk in the top 32
+ // bits; and top(x) is the high 96 bits, also arranged in the low 96
+ // bits of a register, with /zero/ in the top 32 bits.
+ veor q8, q8, q9 // e_0 + e_1 = e
+ vshr128 q1, q3, 32 // top(d t^128)
+ vext.8 d19, d16, d17, #4 // top(e t^64)
+ vshl.u64 d16, d0, #32 // top(f), sort of
+ veor d3, d3, d19 // q1 = top(d t^128 + e t^64)
+ veor d0, d0, d17 // q0 = bot([d t^128] + e t^64 + f)
+ veor d3, d3, d16 // q1 = top(d t^128 + e t^64 + f)
+
+ // Shift the product right by one place (from GCM's point of view),
+ // but, unusually, don't swap the halves, because we need to work on
+ // the 32-bit pieces later. After this, we're in GCM bizarro-world.
+ // q0 = // (?, x_2; x_1, x_0)
+ // q1 = // (0, x_5; x_4, x_3)
+ vshr.u64 d4, d0, #63 // carry from d0 to d1
+ vshr.u64 d5, d2, #63 // carry from d2 to d3
+ vshr.u32 d6, d3, #31 // carry from d3 to d0
+ vshl.u64 q0, q0, #1 // shift low half
+ vshl.u64 q1, q1, #1 // shift high half
+ vorr d1, d1, d4
+ vorr d0, d0, d6
+ vorr d3, d3, d5
+
+ // Finally, the reduction. This is essentially the same as the
+ // 128-bit case, except that the polynomial is p(t) = t^96 + t^10 +
+ // t^9 + t^6 + 1. The degrees are larger but not enough to cause
+ // trouble for the general approach.
+
+ // First, shift the high bits down.
+ vshl.u32 q2, q1, #26 // b_i for t^6
+ vshl.u32 q3, q1, #23 // b_i for t^9
+ vshl.u32 q8, q1, #22 // b_i for t^10
+ veor q2, q2, q3 // add them all together
+ veor q2, q2, q8
+ vshl128 q3, q2, 64 // contribution into high half
+ vshr128 q2, q2, 32 // and low half
+ veor q1, q1, q3 // mix them in
+ veor q0, q0, q2
+
+ // And then shift the low bits up.
+ vshr.u32 q2, q1, #6
+ vshr.u32 q3, q1, #9
+ veor q0, q0, q1 // mix in the unit contribution
+ vshr.u32 q8, q1, #10
+ veor q2, q2, q3 // mix together t^6 and t^9
+ veor q0, q0, q8 // mix in t^10
+ veor q0, q0, q2 // and the rest
+
+ // And finally swap the two halves.
+ vswp d0, d1
+.endm
+
+.macro mul192
+ // Enter with u and v in d0--d2 and d3--d5 respectively; leave
+ // with z = u v in d0--d2. Clobbers q8--q15.
+
+ // Start multiplying and accumulating pieces of product.
+ // (d0; d1; d2) = // (u_0; u_1; u_2)
+ // (d3; d4; d5) = // (v_0; v_1; v_2)
+ vmull.p64 q10, d0, d3 // e = u_0 v_0
+
+ vmull.p64 q12, d0, d4 // u_0 v_1
+ vmull.p64 q13, d1, d3 // u_1 v_0
+
+ vmull.p64 q9, d0, d5 // u_0 v_2
+ vmull.p64 q14, d1, d4 // u_1 v_1
+ vmull.p64 q15, d2, d3 // u_2 v_0
+ veor q12, q12, q13 // d = u_0 v_1 + u_1 v_0
+
+ vmull.p64 q11, d1, d5 // u_1 v_2
+ vmull.p64 q13, d2, d4 // u_2 v_1
+ veor q9, q9, q14 // u_0 v_2 + u_1 v_1
+
+ vmull.p64 q8, d2, d5 // a = u_2 v_2
+ veor q9, q9, q15 // c = u_0 v_2 + u_1 v_1 + u_2 v_0
+ veor q11, q11, q13 // b = u_1 v_2 + u_2 v_1
+
+ // Piece the product together.
+ veor d17, d17, d22 // q8 = // (x_5; x_4)
+ veor d18, d18, d23
+ veor d19, d19, d24 // q9 = // (x_3; x_2)
+ veor d20, d20, d25 // q10 = // (x_1; x_0)
+
+ // Shift the product right by one place (from GCM's point of view).
+ vshr.u64 q11, q8, #63 // carry from d16/d17 to d17/d18
+ vshr.u64 q12, q9, #63 // carry from d18/d19 to d19/d20
+ vshr.u64 d26, d20, #63 // carry from d20 to d21
+ vshl.u64 q8, q8, #1 // shift everything down
+ vshl.u64 q9, q9, #1
+ vshl.u64 q10, q10, #1
+ vorr d17, d17, d22 // and mix in the carries
+ vorr d18, d18, d23
+ vorr d19, d19, d24
+ vorr d20, d20, d25
+ vorr d21, d21, d26
+
+ // Next, the reduction. Our polynomial this time is p(x) = t^192 +
+ // t^7 + t^2 + t + 1. Yes, the magic numbers are the same as the
+ // 128-bit case. I don't know why.
+
+ // First, shift the high bits down.
+ // q8 = // (y_5; y_4)
+ // q9 = // (y_3; y_2)
+ // q10 = // (y_1; y_0)
+ vshl.u64 q11, q8, #63 // (y_5; y_4) b_i for t
+ vshl.u64 d28, d18, #63 // y_3 b_i for t
+ vshl.u64 q12, q8, #62 // (y_5; y_4) b_i for t^2
+ vshl.u64 d29, d18, #62 // y_3 b_i for t^2
+ vshl.u64 q13, q8, #57 // (y_5; y_4) b_i for t^7
+ vshl.u64 d30, d18, #57 // y_3 b_i for t^7
+ veor q11, q11, q12 // mix them all together
+ veor d28, d28, d29
+ veor q11, q11, q13
+ veor d28, d28, d30
+ veor q9, q9, q11
+ veor d20, d20, d28
+
+ // And finally shift the low bits up. Also, switch the order of the
+ // pieces for output.
+ // q8 = // (y'_5; y'_4)
+ // q9 = // (y'_3; y'_2)
+ // q10 = // (y'_1; y'_0)
+ vshr.u64 q11, q8, #1 // (y_5; y_4) a_i for t
+ vshr.u64 d28, d18, #1 // y'_3 a_i for t
+ vshr.u64 q12, q8, #2 // (y_5; y_4) a_i for t^2
+ vshr.u64 d29, d18, #2 // y'_3 a_i for t^2
+ vshr.u64 q13, q8, #7 // (y_5; y_4) a_i for t^7
+ vshr.u64 d30, d18, #7 // y'_3 a_i for t^7
+ veor q8, q8, q11
+ veor d18, d18, d28
+ veor q12, q12, q13
+ veor d29, d29, d30
+ veor q8, q8, q12
+ veor d18, d18, d29
+ veor d0, d21, d18
+ veor d1, d20, d17
+ veor d2, d19, d16
+.endm
+
+.macro mul256
+ // Enter with u and v in q0/q1 and q2/q3 respectively; leave
+ // with z = u v in q0/q1. Clobbers q8--q15.
+
+ // Now it's starting to look worthwhile to do Karatsuba. Suppose
+ // u = u_0 + u_1 B and v = v_0 + v_1 B. Then
+ //
+ // u v = (u_0 v_0) + (u_0 v_1 + u_1 v_0) B + (u_1 v_1) B^2
+ //
+ // Name these coefficients of B^i be a, b, and c, respectively, and
+ // let r = u_0 + u_1 and s = v_0 + v_1. Then observe that
+ //
+ // q = r s = (u_0 + u_1) (v_0 + v_1)
+ // = (u_0 v_0) + (u1 v_1) + (u_0 v_1 + u_1 v_0)
+ // = a + d + c
+ //
+ // The first two terms we've already calculated; the last is the
+ // remaining one we want. We'll set B = t^128. We know how to do
+ // 128-bit multiplications already, and Karatsuba is too annoying
+ // there, so there'll be 12 multiplications altogether, rather than
+ // the 16 we'd have if we did this the naïve way.
+ // q0 = // u_0 = (u_00; u_01)
+ // q1 = // u_1 = (u_10; u_11)
+ // q2 = // v_0 = (v_00; v_01)
+ // q3 = // v_1 = (v_10; v_11)
+
+ veor q8, q0, q1 // u_* = (u_00 + u_10; u_01 + u_11)
+ veor q9, q2, q3 // v_* = (v_00 + v_10; v_01 + v_11)
+
+ // Start by building the cross product, q = u_* v_*.
+ vmull.p64 q14, d16, d19 // u_*0 v_*1
+ vmull.p64 q15, d17, d18 // u_*1 v_*0
+ vmull.p64 q12, d17, d19 // u_*1 v_*1
+ vmull.p64 q13, d16, d18 // u_*0 v_*0
+ veor q14, q14, q15 // u_*0 v_*1 + u_*1 v_*0
+ veor d25, d25, d28 // q12 = // q_1
+ veor d26, d26, d29 // q13 = // q_0
+
+ // Next, work on the low half, a = u_0 v_0.
+ vmull.p64 q14, d0, d5 // u_00 v_01
+ vmull.p64 q15, d1, d4 // u_01 v_00
+ vmull.p64 q10, d1, d5 // u_01 v_01
+ vmull.p64 q11, d0, d4 // u_00 v_00
+ veor q14, q14, q15 // u_00 v_01 + u_01 v_00
+ veor d21, d21, d28 // q10 = // a_1
+ veor d22, d22, d29 // q11 = // a_0
+
+ // Mix the pieces we have so far.
+ veor q12, q12, q10
+ veor q13, q13, q11
+
+ // Finally, the high half, c = u_1 v_1.
+ vmull.p64 q14, d2, d7 // u_10 v_11
+ vmull.p64 q15, d3, d6 // u_11 v_10
+ vmull.p64 q8, d3, d7 // u_11 v_11
+ vmull.p64 q9, d2, d6 // u_10 v_10
+ veor q14, q14, q15 // u_10 v_11 + u_11 v_10
+ veor d17, d17, d28 // q8 = // c_1
+ veor d18, d18, d29 // q9 = // c_0
+
+ // Finish mixing the product together.
+ veor q12, q12, q8 // q12 = // b_1
+ veor q13, q13, q9 // q13 = // b_0
+ veor q9, q9, q12
+ veor q10, q10, q13
+
+ // Shift the product right by one place (from GCM's point of view).
+ vshr.u64 q0, q8, #63 // carry from d16/d17 to d17/d18
+ vshr.u64 q1, q9, #63 // carry from d18/d19 to d19/d20
+ vshr.u64 q2, q10, #63 // carry from d20/d21 to d21/d22
+ vshr.u64 d6, d22, #63 // carry from d22 to d23
+ vshl.u64 q8, q8, #1 // shift everyting down
+ vshl.u64 q9, q9, #1
+ vshl.u64 q10, q10, #1
+ vshl.u64 q11, q11, #1
+ vorr d17, d17, d0
+ vorr d18, d18, d1
+ vorr d19, d19, d2
+ vorr d20, d20, d3
+ vorr d21, d21, d4
+ vorr d22, d22, d5
+ vorr d23, d23, d6
+
+ // Now we must reduce. This is essentially the same as the 192-bit
+ // case above, but more complicated because everything is bigger.
+ // The polynomial this time is p(t) = t^256 + t^10 + t^5 + t^2 + 1.
+
+ // First, shift the high bits down.
+ // q8 = // (y_7; y_6)
+ // q9 = // (y_5; y_4)
+ // q10 = // (y_3; y_2)
+ // q11 = // (y_1; y_0)
+ vshl.u64 q0, q8, #62 // (y_7; y_6) b_i for t^2
+ vshl.u64 q12, q9, #62 // (y_5; y_4) b_i for t^2
+ vshl.u64 q1, q8, #59 // (y_7; y_6) b_i for t^5
+ vshl.u64 q13, q9, #59 // (y_5; y_4) b_i for t^5
+ vshl.u64 q2, q8, #54 // (y_7; y_6) b_i for t^10
+ vshl.u64 q14, q9, #54 // (y_5; y_4) b_i for t^10
+ veor q0, q0, q1 // mix the contributions together
+ veor q12, q12, q13
+ veor q0, q0, q2
+ veor q12, q12, q14
+ veor d19, d19, d0 // and combine into the lower pieces
+ veor d20, d20, d1
+ veor d21, d21, d24
+ veor d22, d22, d25
+
+ // And then shift the low bits up. Also, switch the order of the
+ // pieces for output.
+ // q8 = // (y'_7; y'_6)
+ // q9 = // (y'_5; y'_4)
+ // q10 = // (y'_3; y'_2)
+ // q11 = // (y'_1; y'_0)
+ vshr.u64 q0, q8, #2 // (y_7; y_6) a_i for t^2
+ vshr.u64 q12, q9, #2 // (y_5; y'_4) a_i for t^2
+ vshr.u64 q1, q8, #5 // (y_7; y_6) a_i for t^5
+ vshr.u64 q13, q9, #5 // (y_5; y_4) a_i for t^5
+ vshr.u64 q2, q8, #10 // (y_7; y_6) a_i for t^10
+ vshr.u64 q14, q9, #10 // (y_5; y_4) a_i for t^10
+
+ veor q8, q8, q0 // mix the contributions together
+ veor q1, q1, q2
+ veor q9, q9, q12
+ veor q13, q13, q14
+ veor q8, q8, q1
+ veor q9, q9, q13
+ veor d3, d20, d16 // and output
+ veor d2, d21, d17
+ veor d1, d22, d18
+ veor d0, d23, d19
+.endm
+
+///--------------------------------------------------------------------------
+/// Main code.
+
+// There are a number of representations of field elements in this code and
+// it can be confusing.
+//
+// * The `external format' consists of a sequence of contiguous bytes in
+// memory called a `block'. The GCM spec explains how to interpret this
+// block as an element of a finite field. As discussed extensively, this
+// representation is very annoying for a number of reasons. On the other
+// hand, this code never actually deals with it directly.
+//
+// * The `register format' consists of one or more NEON registers,
+// depending on the block size. The bytes in each 64-bit lane of these
+// registers are in reverse order, compared to the external format.
+//
+// * The `words' format consists of a sequence of bytes, as in the
+// `external format', but, according to the blockcipher in use, the bytes
+// within each 32-bit word may be reversed (`big-endian') or not
+// (`little-endian'). Accordingly, there are separate entry points for
+// each variant, identified with `b' or `l'.
+
+FUNC(gcm_mulk_128b_arm_crypto)
+ // On entry, r0 points to a 128-bit field element A in big-endian
+ // words format; r1 points to a field-element K in register format.
+ // On exit, A is updated with the product A K.
+
+ vld1.8 {q0}, [r0]
+ vld1.8 {q1}, [r1]
+ vrev64.32 q0, q0
+ mul128
+ vrev64.32 q0, q0
+ vst1.8 {q0}, [r0]
+ bx r14
+ENDFUNC
+
+FUNC(gcm_mulk_128l_arm_crypto)
+ // On entry, r0 points to a 128-bit field element A in little-endian
+ // words format; r1 points to a field-element K in register format.
+ // On exit, A is updated with the product A K.
+
+ vld1.8 {q0}, [r0]
+ vld1.8 {q1}, [r1]
+ vrev64.8 q0, q0
+ mul128
+ vrev64.8 q0, q0
+ vst1.8 {q0}, [r0]
+ bx r14
+ENDFUNC
+
+FUNC(gcm_mulk_64b_arm_crypto)
+ // On entry, r0 points to a 64-bit field element A in big-endian
+ // words format; r1 points to a field-element K in register format.
+ // On exit, A is updated with the product A K.
+
+ vld1.8 {d0}, [r0]
+ vld1.8 {d1}, [r1]
+ vrev64.32 d0, d0
+ mul64
+ vrev64.32 d0, d0
+ vst1.8 {d0}, [r0]
+ bx r14
+ENDFUNC
+
+FUNC(gcm_mulk_64l_arm_crypto)
+ // On entry, r0 points to a 64-bit field element A in little-endian
+ // words format; r1 points to a field-element K in register format.
+ // On exit, A is updated with the product A K.
+
+ vld1.8 {d0}, [r0]
+ vld1.8 {d1}, [r1]
+ vrev64.8 d0, d0
+ vzero
+ mul64
+ vrev64.8 d0, d0
+ vst1.8 {d0}, [r0]
+ bx r14
+ENDFUNC
+
+FUNC(gcm_mulk_96b_arm_crypto)
+ // On entry, r0 points to a 96-bit field element A in big-endian
+ // words format; r1 points to a field-element K in register format.
+ // On exit, A is updated with the product A K.
+
+ ldr r3, [r0, #8]
+ mov r12, #0
+ vld1.8 {d0}, [r0]
+ vld1.8 {q1}, [r1]
+ vrev64.32 d0, d0
+ vmov d1, r12, r3
+ vzero
+ mul96
+ vrev64.32 d0, d0
+ vmov r3, d1[1]
+ vst1.8 {d0}, [r0]
+ str r3, [r0, #8]
+ bx r14
+ENDFUNC
+
+FUNC(gcm_mulk_96l_arm_crypto)
+ // On entry, r0 points to a 128-bit field element A in little-endian
+ // words format; r1 points to a field-element K in register format.
+ // On exit, A is updated with the product A K.
+
+ ldr r3, [r0, #8]
+ mov r12, #0
+ vld1.8 {d0}, [r0]
+ vld1.8 {q1}, [r1]
+ vmov d1, r3, r12
+ vrev64.8 q0, q0
+ mul96
+ vrev64.8 q0, q0
+ vmov r3, d1[0]
+ vst1.8 {d0}, [r0]
+ str r3, [r0, #8]
+ bx r14
+ENDFUNC
+
+FUNC(gcm_mulk_192b_arm_crypto)
+ // On entry, r0 points to a 192-bit field element A in big-endian
+ // words format; r1 points to a field-element K in register format.
+ // On exit, A is updated with the product A K.
+
+ vld1.8 {d0-d2}, [r0]
+ vld1.8 {d3-d5}, [r1]
+ vrev64.32 q0, q0
+ vrev64.32 d2, d2
+ mul192
+ vrev64.32 q0, q0
+ vrev64.32 d2, d2
+ vst1.8 {d0-d2}, [r0]
+ bx r14
+ENDFUNC
+
+FUNC(gcm_mulk_192l_arm_crypto)
+ // On entry, r0 points to a 192-bit field element A in little-endian
+ // words format; r1 points to a field-element K in register format.
+ // On exit, A is updated with the product A K.
+
+ vld1.8 {d0-d2}, [r0]
+ vld1.8 {d3-d5}, [r1]
+ vrev64.8 q0, q0
+ vrev64.8 d2, d2
+ mul192
+ vrev64.8 q0, q0
+ vrev64.8 d2, d2
+ vst1.8 {d0-d2}, [r0]
+ bx r14
+ENDFUNC
+
+FUNC(gcm_mulk_256b_arm_crypto)
+ // On entry, r0 points to a 256-bit field element A in big-endian
+ // words format; r1 points to a field-element K in register format.
+ // On exit, A is updated with the product A K.
+
+ vld1.8 {q0, q1}, [r0]
+ vld1.8 {q2, q3}, [r1]
+ vrev64.32 q0, q0
+ vrev64.32 q1, q1
+ mul256
+ vrev64.32 q0, q0
+ vrev64.32 q1, q1
+ vst1.8 {q0, q1}, [r0]
+ bx r14
+ENDFUNC
+
+FUNC(gcm_mulk_256l_arm_crypto)
+ // On entry, r0 points to a 256-bit field element A in little-endian
+ // words format; r1 points to a field-element K in register format.
+ // On exit, A is updated with the product A K.
+
+ vld1.8 {q0, q1}, [r0]
+ vld1.8 {q2, q3}, [r1]
+ vrev64.8 q0, q0
+ vrev64.8 q1, q1
+ mul256
+ vrev64.8 q0, q0
+ vrev64.8 q1, q1
+ vst1.8 {q0, q1}, [r0]
+ bx r14
+ENDFUNC
+
+///----- That's all, folks --------------------------------------------------
--- /dev/null
+/// -*- mode: asm; asm-comment-char: ?/ -*-
+///
+/// GCM acceleration for ARM64 processors
+///
+/// (c) 2019 Straylight/Edgeware
+///
+
+///----- Licensing notice ---------------------------------------------------
+///
+/// This file is part of Catacomb.
+///
+/// Catacomb is free software: you can redistribute it and/or modify it
+/// under the terms of the GNU Library General Public License as published
+/// by the Free Software Foundation; either version 2 of the License, or
+/// (at your option) any later version.
+///
+/// Catacomb is distributed in the hope that it will be useful, but
+/// WITHOUT ANY WARRANTY; without even the implied warranty of
+/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+/// Library General Public License for more details.
+///
+/// You should have received a copy of the GNU Library General Public
+/// License along with Catacomb. If not, write to the Free Software
+/// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+/// USA.
+
+///--------------------------------------------------------------------------
+/// Preliminaries.
+
+#include "config.h"
+#include "asm-common.h"
+
+ .arch armv8-a+crypto
+
+ .text
+
+///--------------------------------------------------------------------------
+/// Multiplication macros.
+
+ // The good news is that we have a fancy instruction to do the
+ // multiplications. The bad news is that it's not particularly well-
+ // suited to the job.
+ //
+ // For one thing, it only does a 64-bit multiplication, so in general
+ // we'll need to synthesize the full-width multiply by hand. For
+ // another thing, it doesn't help with the reduction, so we have to
+ // do that by hand too. And, finally, GCM has crazy bit ordering,
+ // and the instruction does nothing useful for that at all.
+ //
+ // Focusing on that last problem first: the bits aren't in monotonic
+ // significance order unless we permute them. Fortunately, ARM64 has
+ // an instruction which will just permute the bits in each byte for
+ // us, so we don't have to worry about this very much.
+ //
+ // Our main weapons, the `pmull' and `pmull2' instructions, work on
+ // 64-bit operands, in half of a vector register, and produce 128-bit
+ // results. But neither of them will multiply the high half of one
+ // vector by the low half of a second one, so we have a problem,
+ // which we solve by representing one of the operands redundantly:
+ // rather than packing the 64-bit pieces together, we duplicate each
+ // 64-bit piece across both halves of a register.
+ //
+ // The commentary for `mul128' is the most detailed. The other
+ // macros assume that you've already read and understood that.
+
+.macro mul128
+ // Enter with u and v in v0 and v1/v2 respectively, and 0 in v31;
+ // leave with z = u v in v0. Clobbers v1--v6.
+
+ // First for the double-precision multiplication. It's tempting to
+ // use Karatsuba's identity here, but I suspect that loses more in
+ // the shifting, bit-twiddling, and dependency chains that it gains
+ // in saving a multiplication which otherwise pipelines well.
+ // v0 = // (u_0; u_1)
+ // v1/v2 = // (v_0; v_1)
+ pmull2 v3.1q, v0.2d, v1.2d // u_1 v_0
+ pmull v4.1q, v0.1d, v2.1d // u_0 v_1
+ pmull2 v5.1q, v0.2d, v2.2d // (t_1; x_3) = u_1 v_1
+ pmull v6.1q, v0.1d, v1.1d // (x_0; t_0) = u_0 v_0
+
+ // Arrange the pieces to form a double-precision polynomial.
+ eor v3.16b, v3.16b, v4.16b // (m_0; m_1) = u_0 v_1 + u_1 v_0
+ vshr128 v4, v3, 64 // (m_1; 0)
+ vshl128 v3, v3, 64 // (0; m_0)
+ eor v1.16b, v5.16b, v4.16b // (x_2; x_3)
+ eor v0.16b, v6.16b, v3.16b // (x_0; x_1)
+
+ // And now the only remaining difficulty is that the result needs to
+ // be reduced modulo p(t) = t^128 + t^7 + t^2 + t + 1. Let R = t^128
+ // = t^7 + t^2 + t + 1 in our field. So far, we've calculated z_0
+ // and z_1 such that z_0 + z_1 R = u v using the identity R = t^128:
+ // now we must collapse the two halves of y together using the other
+ // identity R = t^7 + t^2 + t + 1.
+ //
+ // We do this by working on y_2 and y_3 separately, so consider y_i
+ // for i = 2 or 3. Certainly, y_i t^{64i} = y_i R t^{64(i-2) =
+ // (t^7 + t^2 + t + 1) y_i t^{64(i-2)}, but we can't use that
+ // directly without breaking up the 64-bit word structure. Instead,
+ // we start by considering just y_i t^7 t^{64(i-2)}, which again
+ // looks tricky. Now, split y_i = a_i + t^57 b_i, with deg a_i < 57;
+ // then
+ //
+ // y_i t^7 t^{64(i-2)} = a_i t^7 t^{64(i-2)} + b_i t^{64(i-1)}
+ //
+ // We can similarly decompose y_i t^2 and y_i t into a pair of 64-bit
+ // contributions to the t^{64(i-2)} and t^{64(i-1)} words, but the
+ // splits are different. This is lovely, with one small snag: when
+ // we do this to y_3, we end up with a contribution back into the
+ // t^128 coefficient word. But notice that only the low seven bits
+ // of this word are affected, so there's no knock-on contribution
+ // into the t^64 word. Therefore, if we handle the high bits of each
+ // word together, and then the low bits, everything will be fine.
+
+ // First, shift the high bits down.
+ ushr v2.2d, v1.2d, #63 // the b_i for t
+ ushr v3.2d, v1.2d, #62 // the b_i for t^2
+ ushr v4.2d, v1.2d, #57 // the b_i for t^7
+ eor v2.16b, v2.16b, v3.16b // add them all together
+ eor v2.16b, v2.16b, v4.16b
+ vshr128 v3, v2, 64
+ vshl128 v4, v2, 64
+ eor v1.16b, v1.16b, v3.16b // contribution into high half
+ eor v0.16b, v0.16b, v4.16b // and low half
+
+ // And then shift the low bits up.
+ shl v2.2d, v1.2d, #1
+ shl v3.2d, v1.2d, #2
+ shl v4.2d, v1.2d, #7
+ eor v1.16b, v1.16b, v2.16b // unit and t contribs
+ eor v3.16b, v3.16b, v4.16b // t^2 and t^7 contribs
+ eor v0.16b, v0.16b, v1.16b // mix everything together
+ eor v0.16b, v0.16b, v3.16b // ... and we're done
+.endm
+
+.macro mul64
+ // Enter with u and v in the low halves of v0 and v1, respectively;
+ // leave with z = u v in x2. Clobbers x2--x4.
+
+ // The multiplication is thankfully easy.
+ // v0 = // (u; ?)
+ // v1 = // (v; ?)
+ pmull v0.1q, v0.1d, v1.1d // u v
+
+ // Now we must reduce. This is essentially the same as the 128-bit
+ // case above, but mostly simpler because everything is smaller. The
+ // polynomial this time is p(t) = t^64 + t^4 + t^3 + t + 1.
+
+ // Before we get stuck in, transfer the product to general-purpose
+ // registers.
+ mov x3, v0.d[1]
+ mov x2, v0.d[0]
+
+ // First, shift the high bits down.
+ eor x4, x3, x3, lsr #1 // pre-mix t^3 and t^4
+ eor x3, x3, x3, lsr #63 // mix in t contribution
+ eor x3, x3, x4, lsr #60 // shift and mix in t^3 and t^4
+
+ // And then shift the low bits up.
+ eor x3, x3, x3, lsl #1 // mix unit and t; pre-mix t^3, t^4
+ eor x2, x2, x3 // fold them in
+ eor x2, x2, x3, lsl #3 // and t^3 and t^4
+.endm
+
+.macro mul96
+ // Enter with u in the least-significant 96 bits of v0, with zero in
+ // the upper 32 bits, and with the least-significant 64 bits of v in
+ // both halves of v1, and the upper 32 bits of v in the low 32 bits
+ // of each half of v2, with zero in the upper 32 bits; and with zero
+ // in v31. Yes, that's a bit hairy. Leave with the product u v in
+ // the low 96 bits of v0, and /junk/ in the high 32 bits. Clobbers
+ // v1--v6.
+
+ // This is an inconvenient size. There's nothing for it but to do
+ // four multiplications, as if for the 128-bit case. It's possible
+ // that there's cruft in the top 32 bits of the input registers, so
+ // shift both of them up by four bytes before we start. This will
+ // mean that the high 64 bits of the result (from GCM's viewpoint)
+ // will be zero.
+ // v0 = // (u_0 + u_1 t^32; u_2)
+ // v1 = // (v_0 + v_1 t^32; v_0 + v_1 t^32)
+ // v2 = // (v_2; v_2)
+ pmull2 v5.1q, v0.2d, v1.2d // u_2 (v_0 + v_1 t^32) t^32 = e_0
+ pmull v4.1q, v0.1d, v2.1d // v_2 (u_0 + u_1 t^32) t^32 = e_1
+ pmull2 v6.1q, v0.2d, v2.2d // u_2 v_2 = d = (d; 0)
+ pmull v3.1q, v0.1d, v1.1d // u_0 v_0 + (u_0 v_1 + u_1 v_0) t^32
+ // + u_1 v_1 t^64 = f
+
+ // Extract the high and low halves of the 192-bit result. The answer
+ // we want is d t^128 + e t^64 + f, where e = e_0 + e_1. The low 96
+ // bits of the answer will end up in v0, with junk in the top 32
+ // bits; the high 96 bits will end up in v1, which must have zero in
+ // its top 32 bits.
+ //
+ // Here, bot(x) is the low 96 bits of a 192-bit quantity x, arranged
+ // in the low 96 bits of a SIMD register, with junk in the top 32
+ // bits; and top(x) is the high 96 bits, also arranged in the low 96
+ // bits of a register, with /zero/ in the top 32 bits.
+ eor v4.16b, v4.16b, v5.16b // e_0 + e_1 = e
+ vshl128 v6, v6, 32 // top(d t^128)
+ vshr128 v5, v4, 32 // top(e t^64)
+ vshl128 v4, v4, 64 // bot(e t^64)
+ vshr128 v1, v3, 96 // top(f)
+ eor v6.16b, v6.16b, v5.16b // top(d t^128 + e t^64)
+ eor v0.16b, v3.16b, v4.16b // bot([d t^128] + e t^64 + f)
+ eor v1.16b, v1.16b, v6.16b // top(e t^64 + d t^128 + f)
+
+ // Finally, the reduction. This is essentially the same as the
+ // 128-bit case, except that the polynomial is p(t) = t^96 + t^10 +
+ // t^9 + t^6 + 1. The degrees are larger but not enough to cause
+ // trouble for the general approach. Unfortunately, we have to do
+ // this in 32-bit pieces rather than 64.
+
+ // First, shift the high bits down.
+ ushr v2.4s, v1.4s, #26 // the b_i for t^6
+ ushr v3.4s, v1.4s, #23 // the b_i for t^9
+ ushr v4.4s, v1.4s, #22 // the b_i for t^10
+ eor v2.16b, v2.16b, v3.16b // add them all together
+ eor v2.16b, v2.16b, v4.16b
+ vshr128 v3, v2, 64 // contribution for high half
+ vshl128 v2, v2, 32 // contribution for low half
+ eor v1.16b, v1.16b, v3.16b // apply to high half
+ eor v0.16b, v0.16b, v2.16b // and low half
+
+ // And then shift the low bits up.
+ shl v2.4s, v1.4s, #6
+ shl v3.4s, v1.4s, #9
+ shl v4.4s, v1.4s, #10
+ eor v1.16b, v1.16b, v2.16b // unit and t^6 contribs
+ eor v3.16b, v3.16b, v4.16b // t^9 and t^10 contribs
+ eor v0.16b, v0.16b, v1.16b // mix everything together
+ eor v0.16b, v0.16b, v3.16b // ... and we're done
+.endm
+
+.macro mul192
+ // Enter with u in v0 and the less-significant half of v1, with v
+ // duplicated across both halves of v2/v3/v4, and with zero in v31.
+ // Leave with the product u v in v0 and the bottom half of v1.
+ // Clobbers v16--v25.
+
+ // Start multiplying and accumulating pieces of product.
+ // v0 = // (u_0; u_1)
+ // v1 = // (u_2; ?)
+ // v2 = // (v_0; v_0)
+ // v3 = // (v_1; v_1)
+ // v4 = // (v_2; v_2)
+ pmull v16.1q, v0.1d, v2.1d // a = u_0 v_0
+
+ pmull v19.1q, v0.1d, v3.1d // u_0 v_1
+ pmull2 v21.1q, v0.2d, v2.2d // u_1 v_0
+
+ pmull v17.1q, v0.1d, v4.1d // u_0 v_2
+ pmull2 v22.1q, v0.2d, v3.2d // u_1 v_1
+ pmull v23.1q, v1.1d, v2.1d // u_2 v_0
+ eor v19.16b, v19.16b, v21.16b // b = u_0 v_1 + u_1 v_0
+
+ pmull2 v20.1q, v0.2d, v4.2d // u_1 v_2
+ pmull v24.1q, v1.1d, v3.1d // u_2 v_1
+ eor v17.16b, v17.16b, v22.16b // u_0 v_2 + u_1 v_1
+
+ pmull v18.1q, v1.1d, v4.1d // e = u_2 v_2
+ eor v17.16b, v17.16b, v23.16b // c = u_0 v_2 + u_1 v_1 + u_2 v_1
+ eor v20.16b, v20.16b, v24.16b // d = u_1 v_2 + u_2 v_1
+
+ // Piece the product together.
+ // v16 = // (a_0; a_1)
+ // v19 = // (b_0; b_1)
+ // v17 = // (c_0; c_1)
+ // v20 = // (d_0; d_1)
+ // v18 = // (e_0; e_1)
+ vshl128 v21, v19, 64 // (0; b_0)
+ ext v22.16b, v19.16b, v20.16b, #8 // (b_1; d_0)
+ vshr128 v23, v20, 64 // (d_1; 0)
+ eor v16.16b, v16.16b, v21.16b // (x_0; x_1)
+ eor v17.16b, v17.16b, v22.16b // (x_2; x_3)
+ eor v18.16b, v18.16b, v23.16b // (x_2; x_3)
+
+ // Next, the reduction. Our polynomial this time is p(x) = t^192 +
+ // t^7 + t^2 + t + 1. Yes, the magic numbers are the same as the
+ // 128-bit case. I don't know why.
+
+ // First, shift the high bits down.
+ // v16 = // (y_0; y_1)
+ // v17 = // (y_2; y_3)
+ // v18 = // (y_4; y_5)
+ mov v19.d[0], v17.d[1] // (y_3; ?)
+
+ ushr v23.2d, v18.2d, #63 // hi b_i for t
+ ushr d20, d19, #63 // lo b_i for t
+ ushr v24.2d, v18.2d, #62 // hi b_i for t^2
+ ushr d21, d19, #62 // lo b_i for t^2
+ ushr v25.2d, v18.2d, #57 // hi b_i for t^7
+ ushr d22, d19, #57 // lo b_i for t^7
+ eor v23.16b, v23.16b, v24.16b // mix them all together
+ eor v20.8b, v20.8b, v21.8b
+ eor v23.16b, v23.16b, v25.16b
+ eor v20.8b, v20.8b, v22.8b
+
+ // Permute the high pieces while we fold in the b_i.
+ eor v17.16b, v17.16b, v23.16b
+ vshl128 v20, v20, 64
+ mov v19.d[0], v18.d[1] // (y_5; ?)
+ ext v18.16b, v17.16b, v18.16b, #8 // (y_3; y_4)
+ eor v16.16b, v16.16b, v20.16b
+
+ // And finally shift the low bits up.
+ // v16 = // (y'_0; y'_1)
+ // v17 = // (y'_2; ?)
+ // v18 = // (y'_3; y'_4)
+ // v19 = // (y'_5; ?)
+ shl v20.2d, v18.2d, #1
+ shl d23, d19, #1
+ shl v21.2d, v18.2d, #2
+ shl d24, d19, #2
+ shl v22.2d, v18.2d, #7
+ shl d25, d19, #7
+ eor v18.16b, v18.16b, v20.16b // unit and t contribs
+ eor v19.8b, v19.8b, v23.8b
+ eor v21.16b, v21.16b, v22.16b // t^2 and t^7 contribs
+ eor v24.8b, v24.8b, v25.8b
+ eor v18.16b, v18.16b, v21.16b // all contribs
+ eor v19.8b, v19.8b, v24.8b
+ eor v0.16b, v16.16b, v18.16b // mix them into the low half
+ eor v1.8b, v17.8b, v19.8b
+.endm
+
+.macro mul256
+ // Enter with u in v0/v1, with v duplicated across both halves of
+ // v2--v5, and with zero in v31. Leave with the product u v in
+ // v0/v1. Clobbers ???.
+
+ // Now it's starting to look worthwhile to do Karatsuba. Suppose
+ // u = u_0 + u_1 B and v = v_0 + v_1 B. Then
+ //
+ // u v = (u_0 v_0) + (u_0 v_1 + u_1 v_0) B + (u_1 v_1) B^2
+ //
+ // Name these coefficients of B^i be a, b, and c, respectively, and
+ // let r = u_0 + u_1 and s = v_0 + v_1. Then observe that
+ //
+ // q = r s = (u_0 + u_1) (v_0 + v_1)
+ // = (u_0 v_0) + (u1 v_1) + (u_0 v_1 + u_1 v_0)
+ // = a + d + c
+ //
+ // The first two terms we've already calculated; the last is the
+ // remaining one we want. We'll set B = t^128. We know how to do
+ // 128-bit multiplications already, and Karatsuba is too annoying
+ // there, so there'll be 12 multiplications altogether, rather than
+ // the 16 we'd have if we did this the naïve way.
+ // v0 = // u_0 = (u_00; u_01)
+ // v1 = // u_1 = (u_10; u_11)
+ // v2 = // (v_00; v_00)
+ // v3 = // (v_01; v_01)
+ // v4 = // (v_10; v_10)
+ // v5 = // (v_11; v_11)
+
+ eor v28.16b, v0.16b, v1.16b // u_* = (u_00 + u_10; u_01 + u_11)
+ eor v29.16b, v2.16b, v4.16b // v_*0 = v_00 + v_10
+ eor v30.16b, v3.16b, v5.16b // v_*1 = v_01 + v_11
+
+ // Start by building the cross product, q = u_* v_*.
+ pmull v24.1q, v28.1d, v30.1d // u_*0 v_*1
+ pmull2 v25.1q, v28.2d, v29.2d // u_*1 v_*0
+ pmull v20.1q, v28.1d, v29.1d // u_*0 v_*0
+ pmull2 v21.1q, v28.2d, v30.2d // u_*1 v_*1
+ eor v24.16b, v24.16b, v25.16b // u_*0 v_*1 + u_*1 v_*0
+ vshr128 v25, v24, 64
+ vshl128 v24, v24, 64
+ eor v20.16b, v20.16b, v24.16b // q_0
+ eor v21.16b, v21.16b, v25.16b // q_1
+
+ // Next, work on the low half, a = u_0 v_0
+ pmull v24.1q, v0.1d, v3.1d // u_00 v_01
+ pmull2 v25.1q, v0.2d, v2.2d // u_01 v_00
+ pmull v16.1q, v0.1d, v2.1d // u_00 v_00
+ pmull2 v17.1q, v0.2d, v3.2d // u_01 v_01
+ eor v24.16b, v24.16b, v25.16b // u_00 v_01 + u_01 v_00
+ vshr128 v25, v24, 64
+ vshl128 v24, v24, 64
+ eor v16.16b, v16.16b, v24.16b // a_0
+ eor v17.16b, v17.16b, v25.16b // a_1
+
+ // Mix the pieces we have so far.
+ eor v20.16b, v20.16b, v16.16b
+ eor v21.16b, v21.16b, v17.16b
+
+ // Finally, work on the high half, c = u_1 v_1
+ pmull v24.1q, v1.1d, v5.1d // u_10 v_11
+ pmull2 v25.1q, v1.2d, v4.2d // u_11 v_10
+ pmull v18.1q, v1.1d, v4.1d // u_10 v_10
+ pmull2 v19.1q, v1.2d, v5.2d // u_11 v_11
+ eor v24.16b, v24.16b, v25.16b // u_10 v_11 + u_11 v_10
+ vshr128 v25, v24, 64
+ vshl128 v24, v24, 64
+ eor v18.16b, v18.16b, v24.16b // c_0
+ eor v19.16b, v19.16b, v25.16b // c_1
+
+ // Finish mixing the product together.
+ eor v20.16b, v20.16b, v18.16b
+ eor v21.16b, v21.16b, v19.16b
+ eor v17.16b, v17.16b, v20.16b
+ eor v18.16b, v18.16b, v21.16b
+
+ // Now we must reduce. This is essentially the same as the 192-bit
+ // case above, but more complicated because everything is bigger.
+ // The polynomial this time is p(t) = t^256 + t^10 + t^5 + t^2 + 1.
+ // v16 = // (y_0; y_1)
+ // v17 = // (y_2; y_3)
+ // v18 = // (y_4; y_5)
+ // v19 = // (y_6; y_7)
+ ushr v24.2d, v18.2d, #62 // (y_4; y_5) b_i for t^2
+ ushr v25.2d, v19.2d, #62 // (y_6; y_7) b_i for t^2
+ ushr v26.2d, v18.2d, #59 // (y_4; y_5) b_i for t^5
+ ushr v27.2d, v19.2d, #59 // (y_6; y_7) b_i for t^5
+ ushr v28.2d, v18.2d, #54 // (y_4; y_5) b_i for t^10
+ ushr v29.2d, v19.2d, #54 // (y_6; y_7) b_i for t^10
+ eor v24.16b, v24.16b, v26.16b // mix the contributions together
+ eor v25.16b, v25.16b, v27.16b
+ eor v24.16b, v24.16b, v28.16b
+ eor v25.16b, v25.16b, v29.16b
+ vshr128 v26, v25, 64 // slide contribs into position
+ ext v25.16b, v24.16b, v25.16b, #8
+ vshl128 v24, v24, 64
+ eor v18.16b, v18.16b, v26.16b
+ eor v17.16b, v17.16b, v25.16b
+ eor v16.16b, v16.16b, v24.16b
+
+ // And then shift the low bits up.
+ // v16 = // (y'_0; y'_1)
+ // v17 = // (y'_2; y'_3)
+ // v18 = // (y'_4; y'_5)
+ // v19 = // (y'_6; y'_7)
+ shl v24.2d, v18.2d, #2 // (y'_4; y_5) a_i for t^2
+ shl v25.2d, v19.2d, #2 // (y_6; y_7) a_i for t^2
+ shl v26.2d, v18.2d, #5 // (y'_4; y_5) a_i for t^5
+ shl v27.2d, v19.2d, #5 // (y_6; y_7) a_i for t^5
+ shl v28.2d, v18.2d, #10 // (y'_4; y_5) a_i for t^10
+ shl v29.2d, v19.2d, #10 // (y_6; y_7) a_i for t^10
+ eor v18.16b, v18.16b, v24.16b // mix the contributions together
+ eor v19.16b, v19.16b, v25.16b
+ eor v26.16b, v26.16b, v28.16b
+ eor v27.16b, v27.16b, v29.16b
+ eor v18.16b, v18.16b, v26.16b
+ eor v19.16b, v19.16b, v27.16b
+ eor v0.16b, v16.16b, v18.16b
+ eor v1.16b, v17.16b, v19.16b
+.endm
+
+///--------------------------------------------------------------------------
+/// Main code.
+
+// There are a number of representations of field elements in this code and
+// it can be confusing.
+//
+// * The `external format' consists of a sequence of contiguous bytes in
+// memory called a `block'. The GCM spec explains how to interpret this
+// block as an element of a finite field. As discussed extensively, this
+// representation is very annoying for a number of reasons. On the other
+// hand, this code never actually deals with it directly.
+//
+// * The `register format' consists of one or more SIMD registers,
+// depending on the block size. The bits in each byte are reversed,
+// compared to the external format, which makes the polynomials
+// completely vanilla, unlike all of the other GCM implementations.
+//
+// * The `table format' is just like the `register format', only the two
+// halves of 128-bit SIMD register are the same, so we need twice as many
+// registers.
+//
+// * The `words' format consists of a sequence of bytes, as in the
+// `external format', but, according to the blockcipher in use, the bytes
+// within each 32-bit word may be reversed (`big-endian') or not
+// (`little-endian'). Accordingly, there are separate entry points for
+// each variant, identified with `b' or `l'.
+
+FUNC(gcm_mulk_128b_arm64_pmull)
+ // On entry, x0 points to a 128-bit field element A in big-endian
+ // words format; x1 points to a field-element K in table format. On
+ // exit, A is updated with the product A K.
+
+ ldr q0, [x0]
+ ldp q1, q2, [x1]
+ rev32 v0.16b, v0.16b
+ vzero
+ rbit v0.16b, v0.16b
+ mul128
+ rbit v0.16b, v0.16b
+ rev32 v0.16b, v0.16b
+ str q0, [x0]
+ ret
+ENDFUNC
+
+FUNC(gcm_mulk_128l_arm64_pmull)
+ // On entry, x0 points to a 128-bit field element A in little-endian
+ // words format; x1 points to a field-element K in table format. On
+ // exit, A is updated with the product A K.
+
+ ldr q0, [x0]
+ ldp q1, q2, [x1]
+ vzero
+ rbit v0.16b, v0.16b
+ mul128
+ rbit v0.16b, v0.16b
+ str q0, [x0]
+ ret
+ENDFUNC
+
+FUNC(gcm_mulk_64b_arm64_pmull)
+ // On entry, x0 points to a 64-bit field element A in big-endian
+ // words format; x1 points to a field-element K in table format. On
+ // exit, A is updated with the product A K.
+
+ ldr d0, [x0]
+ ldr q1, [x1]
+ rev32 v0.8b, v0.8b
+ rbit v0.8b, v0.8b
+ mul64
+ rbit x2, x2
+ ror x2, x2, #32
+ str x2, [x0]
+ ret
+ENDFUNC
+
+FUNC(gcm_mulk_64l_arm64_pmull)
+ // On entry, x0 points to a 64-bit field element A in little-endian
+ // words format; x1 points to a field-element K in table format. On
+ // exit, A is updated with the product A K.
+
+ ldr d0, [x0]
+ ldr q1, [x1]
+ rbit v0.8b, v0.8b
+ mul64
+ rbit x2, x2
+ rev x2, x2
+ str x2, [x0]
+ ret
+ENDFUNC
+
+FUNC(gcm_mulk_96b_arm64_pmull)
+ // On entry, x0 points to a 96-bit field element A in big-endian
+ // words format; x1 points to a field-element K in table format. On
+ // exit, A is updated with the product A K.
+
+ ldr w2, [x0, #8]
+ ldr d0, [x0, #0]
+ mov v0.d[1], x2
+ ldp q1, q2, [x1]
+ rev32 v0.16b, v0.16b
+ vzero
+ rbit v0.16b, v0.16b
+ mul96
+ rbit v0.16b, v0.16b
+ rev32 v0.16b, v0.16b
+ mov w2, v0.s[2]
+ str d0, [x0, #0]
+ str w2, [x0, #8]
+ ret
+ENDFUNC
+
+FUNC(gcm_mulk_96l_arm64_pmull)
+ // On entry, x0 points to a 96-bit field element A in little-endian
+ // words format; x1 points to a field-element K in table format. On
+ // exit, A is updated with the product A K.
+
+ ldr d0, [x0, #0]
+ ldr w2, [x0, #8]
+ mov v0.d[1], x2
+ ldp q1, q2, [x1]
+ rbit v0.16b, v0.16b
+ vzero
+ mul96
+ rbit v0.16b, v0.16b
+ mov w2, v0.s[2]
+ str d0, [x0, #0]
+ str w2, [x0, #8]
+ ret
+ENDFUNC
+
+FUNC(gcm_mulk_192b_arm64_pmull)
+ // On entry, x0 points to a 192-bit field element A in big-endian
+ // words format; x1 points to a field-element K in table format. On
+ // exit, A is updated with the product A K.
+
+ ldr q0, [x0, #0]
+ ldr d1, [x0, #16]
+ ldp q2, q3, [x1, #0]
+ ldr q4, [x1, #32]
+ rev32 v0.16b, v0.16b
+ rev32 v1.8b, v1.8b
+ rbit v0.16b, v0.16b
+ rbit v1.8b, v1.8b
+ vzero
+ mul192
+ rev32 v0.16b, v0.16b
+ rev32 v1.8b, v1.8b
+ rbit v0.16b, v0.16b
+ rbit v1.8b, v1.8b
+ str q0, [x0, #0]
+ str d1, [x0, #16]
+ ret
+ENDFUNC
+
+FUNC(gcm_mulk_192l_arm64_pmull)
+ // On entry, x0 points to a 192-bit field element A in little-endian
+ // words format; x1 points to a field-element K in table format. On
+ // exit, A is updated with the product A K.
+
+ ldr q0, [x0, #0]
+ ldr d1, [x0, #16]
+ ldp q2, q3, [x1, #0]
+ ldr q4, [x1, #32]
+ rbit v0.16b, v0.16b
+ rbit v1.8b, v1.8b
+ vzero
+ mul192
+ rbit v0.16b, v0.16b
+ rbit v1.8b, v1.8b
+ str q0, [x0, #0]
+ str d1, [x0, #16]
+ ret
+ENDFUNC
+
+FUNC(gcm_mulk_256b_arm64_pmull)
+ // On entry, x0 points to a 256-bit field element A in big-endian
+ // words format; x1 points to a field-element K in table format. On
+ // exit, A is updated with the product A K.
+
+ ldp q0, q1, [x0]
+ ldp q2, q3, [x1, #0]
+ ldp q4, q5, [x1, #32]
+ rev32 v0.16b, v0.16b
+ rev32 v1.16b, v1.16b
+ rbit v0.16b, v0.16b
+ rbit v1.16b, v1.16b
+ vzero
+ mul256
+ rev32 v0.16b, v0.16b
+ rev32 v1.16b, v1.16b
+ rbit v0.16b, v0.16b
+ rbit v1.16b, v1.16b
+ stp q0, q1, [x0]
+ ret
+ENDFUNC
+
+FUNC(gcm_mulk_256l_arm64_pmull)
+ // On entry, x0 points to a 256-bit field element A in little-endian
+ // words format; x1 points to a field-element K in table format. On
+ // exit, A is updated with the product A K.
+
+ ldp q0, q1, [x0]
+ ldp q2, q3, [x1, #0]
+ ldp q4, q5, [x1, #32]
+ rbit v0.16b, v0.16b
+ rbit v1.16b, v1.16b
+ vzero
+ mul256
+ rbit v0.16b, v0.16b
+ rbit v1.16b, v1.16b
+ stp q0, q1, [x0]
+ ret
+ENDFUNC
+
+///----- That's all, folks --------------------------------------------------
--- /dev/null
+/* -*-c-*-
+ *
+ * The GCM authenticated encryption mode
+ *
+ * (c) 2018 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef CATACOMB_GCM_DEF_H
+#define CATACOMB_GCM_DEF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#ifndef CATACOMB_ARENA_H
+# include "arena.h"
+#endif
+
+#ifndef CATACOMB_BLKC_H
+# include "blkc.h"
+#endif
+
+#ifndef CATACOMB_CT_H
+# include "ct.h"
+#endif
+
+#ifndef CATACOMB_KEYSZ_H
+# include "keysz.h"
+#endif
+
+#ifndef CATACOMB_PARANOIA_H
+# include "paranoia.h"
+#endif
+
+#ifndef CATACOMB_RSVR_H
+# include "rsvr.h"
+#endif
+
+/*----- Type definitions --------------------------------------------------*/
+
+typedef struct gcm_params {
+ unsigned f; /* flags */
+#define GCMF_SWAP 1u /* swap byte order? */
+ unsigned n; /* number of words in block */
+ uint32 poly; /* selected polynomial mask */
+} gcm_params;
+
+/*----- Utilities ---------------------------------------------------------*/
+
+/* Supported block sizes. */
+#define GCM_WIDTHS(_) _(64) _(96) _(128) _(192) _(256)
+#define GCM_NMAX 8
+
+/* Polynomial tails for the supported block sizes. */
+#define GCM_POLY_64 0xd8000000
+#define GCM_POLY_96 0x82600000
+#define GCM_POLY_128 0xe1000000
+#define GCM_POLY_192 0xe1000000
+#define GCM_POLY_256 0xa4200000
+
+/* Determine whether to set the @GCMF_SWAP@ flag. */
+#define GCM_SWAP_L GCMF_SWAP
+#define GCM_SWAP_B 0
+
+/* --- @gcm_mktable@ --- *
+ *
+ * Arguments: @const gcm_params *p@ = pointer to the parameters
+ * @uint32 *ktab@ = where to write the table; there must be
+ * space for %$32 n$% $%n$%-word entries, i.e.,
+ * %$32 n^2$% 32-bit words in total, where %$n$% is
+ * @p->n@, the block size in words
+ * @const uint32 *k@ = input field element
+ *
+ * Returns: ---
+ *
+ * Use: Construct a table for use by @gcm_mulk_...@ below, to
+ * multiply (vaguely) efficiently by @k@.
+ */
+
+extern void gcm_mktable(const gcm_params */*p*/,
+ uint32 */*ktab*/, const uint32 */*k*/);
+
+/* --- @gcm_mulk_N{b,l}@ --- *
+ *
+ * Arguments: @uint32 *a@ = accumulator to multiply
+ * @const uint32 *ktab@ = table constructed by @gcm_mktable@
+ *
+ * Returns: ---
+ *
+ * Use: Multiply @a@ by @k@ (implicitly represented in @ktab@),
+ * updating @a@ in-place. There are separate functions for each
+ * supported block size and endianness because this is the
+ * function whose performance actually matters.
+ */
+
+#define GCM_DECL_MULK(nbits) \
+ extern void gcm_mulk_##nbits##b(uint32 */*a*/, const uint32 */*ktab*/); \
+ extern void gcm_mulk_##nbits##l(uint32 */*a*/, const uint32 */*ktab*/);
+GCM_WIDTHS(GCM_DECL_MULK)
+#undef GCM_DECL_MULK
+
+/* Dispatch to the appropriate variant of @gcm_mulk@. */
+#define GCM_MULK(PRE, a, ktab) \
+ BLKC_GLUE(GCM_MULK_, BLKC_ENDIAN(PRE))(BLKC_BITS(PRE), a, ktab)
+#define GCM_MULK_B(nbits, a, ktab) \
+ BLKC_GLUE(BLKC_GLUE(gcm_mulk_, nbits), b)(a, ktab)
+#define GCM_MULK_L(nbits, a, ktab) \
+ BLKC_GLUE(BLKC_GLUE(gcm_mulk_, nbits), l)(a, ktab)
+
+/* --- @gcm_ghashdone@ --- *
+ *
+ * Arguments: @const gcm_params *p@ = pointer to the parameters
+ * @uint32 *a@ = GHASH accumulator
+ * @const uint32 *ktab@ = multiplication table, built by
+ * @gcm_mktable@
+ * @unsigned long xblocks, yblocks@ = number of whole blocks in
+ * the two inputs
+ * @unsigned xbytes, ybytes@ = number of trailing bytes in the
+ * two inputs
+ *
+ * Returns: ---
+ *
+ * Use: Finishes a GHASH operation by appending the appropriately
+ * encoded lengths of the two constituent messages.
+ */
+
+extern void gcm_ghashdone(const gcm_params */*p*/,
+ uint32 */*a*/, const uint32 */*ktab*/,
+ unsigned long /*xblocks*/, unsigned /*xbytes*/,
+ unsigned long /*yblocks*/, unsigned /*ybytes*/);
+
+/* --- @gcm_concat@ --- *
+ *
+ * Arguments: @const gcm_params *p@ = pointer to the parameters
+ * @uint32 *z@ = GHASH accumulator for suffix, updated
+ * @const uint32 *x@ = GHASH accumulator for prefix
+ * @const uint32 *ktab@ = multiplication table, built by
+ * @gcm_mktable@
+ * @unsigned long n@ = length of suffix in whole blocks
+ *
+ * Returns: ---
+ *
+ * Use: On entry, @x@ and @z@ are the results of hashing two strings
+ * %$a$% and %$b$%, each a whole number of blocks long; in
+ * particular, %$b$% is @n@ blocks long. On exit, @z@ is
+ * updated to be the hash of %$a \cat b$%.
+ */
+
+extern void gcm_concat(const gcm_params */*p*/,
+ uint32 */*z*/, const uint32 */*x*/,
+ const uint32 */*ktab*/, unsigned long /*n*/);
+
+/* Step the counter using GCM's strange only-the-last-32-bits convention. */
+#define GCM_STEP(PRE, w) BLKC_GLUE(GCM_STEP_, BLKC_ENDIAN(PRE))(PRE, w)
+#define GCM_STEP_B(PRE, w) GCM_STEP_X(PRE, BLKC_ID, w)
+#define GCM_STEP_L(PRE, w) GCM_STEP_X(PRE, ENDSWAP32, w)
+#define GCM_STEP_X(PRE, op, w) do { \
+ BLKC_W(w); \
+ _w[PRE##_BLKSZ/4 - 1] = op(op(_w[PRE##_BLKSZ/4 - 1]) + 1); \
+} while (0)
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @GCM_DEF@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Creates an implementation for the GCM authenticated-
+ * encryption mode.
+ */
+
+#define GCM_DEF(PRE, pre) GCM_DEFX(PRE, pre, #pre, #pre)
+
+#define GCM_DEFX(PRE, pre, name, fname) \
+ \
+static const gcm_params pre##_gcmparams = { \
+ BLKC_GLUE(GCM_SWAP_, BLKC_ENDIAN(PRE)), \
+ PRE##_BLKSZ/4, \
+ BLKC_GLUE(GCM_POLY_, BLKC_BITS(PRE)) \
+}; \
+ \
+const octet \
+ pre##_gcmnoncesz[] = { KSZ_ANY, PRE##_BLKSZ - 4 }, \
+ pre##_gcmtagsz[] = { KSZ_RANGE, PRE##_BLKSZ, 0, PRE##_BLKSZ, 1 }; \
+ \
+static const rsvr_policy pre##_gcmpolicy = { 0, PRE##_BLKSZ, PRE##_BLKSZ }; \
+ \
+/* --- @pre_gcmsetkey@ --- * \
+ * \
+ * Arguments: @pre_gcmkey *key@ = pointer to key block to fill in \
+ * @const void *k@ = pointer to key material \
+ * @size_t ksz@ = size of key material \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes an GCM key block. \
+ */ \
+ \
+void pre##_gcmsetkey(pre##_gcmkey *key, const void *k, size_t ksz) \
+{ \
+ uint32 t[PRE##_BLKSZ/4]; \
+ \
+ /* Initialize the block cipher. */ \
+ pre##_init(&key->ctx, k, ksz); \
+ \
+ /* Set up the GHASH multiplication table. */ \
+ BLKC_ZERO(PRE, t); pre##_eblk(&key->ctx, t, t); \
+ gcm_mktable(&pre##_gcmparams, key->ktab, t); \
+} \
+ \
+/* --- @pre_gcmaadinit@ --- * \
+ * \
+ * Arguments: @pre_gcmaadctx *aad@ = pointer to AAD context \
+ * @const pre_gcmkey *key@ = pointer to key block \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes an GCM AAD (`additional authenticated \
+ * data') context associated with a given key. AAD \
+ * contexts can be copied and/or reused, saving time if \
+ * the AAD for a number of messages has a common prefix. \
+ * \
+ * The @key@ doesn't need to be kept around, though \
+ * usually there'll at least be another copy in some GCM \
+ * operation context because the AAD on its own isn't much \
+ * good. \
+ */ \
+ \
+void pre##_gcmaadinit(pre##_gcmaadctx *aad, const pre##_gcmkey *key) \
+ { aad->k = *key; aad->off = 0; aad->len = 0; BLKC_ZERO(PRE, aad->a); } \
+ \
+/* --- @pre_gcmaadhash@ --- * \
+ * \
+ * Arguments: @pre_gcmaadctx *aad@ = pointer to AAD context \
+ * @const void *p@ = pointer to AAD material \
+ * @size_t sz@ = length of AAD material \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Feeds AAD into the context. \
+ */ \
+ \
+void pre##_gcmaadhash(pre##_gcmaadctx *aad, const void *p, size_t sz) \
+{ \
+ rsvr_state st; \
+ const octet *q; \
+ \
+ rsvr_setup(&st, &pre##_gcmpolicy, aad->b, &aad->off, p, sz); \
+ RSVR_DO(&st) while ((q = RSVR_NEXT(&st, PRE##_BLKSZ)) != 0) { \
+ BLKC_XLOAD(PRE, aad->a, q); GCM_MULK(PRE, aad->a, aad->k.ktab); \
+ aad->len++; \
+ } \
+} \
+ \
+/* --- @pre_gcminit@ --- * \
+ * \
+ * Arguments: @pre_gcmctx *ctx@ = pointer to GCM context \
+ * @const pre_gcmkey *key@ = pointer to key block \
+ * @const void *n@ = pointer to nonce \
+ * @size_t nsz@ = size of nonce \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initialize an GCM operation context with a given key. \
+ * \
+ * The original key needn't be kept around any more. \
+ */ \
+ \
+void pre##_gcminit(pre##_gcmctx *ctx, const pre##_gcmkey *k, \
+ const void *n, size_t nsz) \
+ { ctx->k = *k; pre##_gcmreinit(ctx, n, nsz); } \
+ \
+/* --- @pre_gcmreinit@ --- * \
+ * \
+ * Arguments: @pre_gcmctx *ctx@ = pointer to GCM context \
+ * @const void *n@ = pointer to nonce \
+ * @size_t nsz@ = size of nonce \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Reinitialize an GCM operation context, changing the \
+ * nonce. \
+ */ \
+ \
+void pre##_gcmreinit(pre##_gcmctx *ctx, const void *n, size_t nsz) \
+{ \
+ octet b[PRE##_BLKSZ]; \
+ const octet *q = n; \
+ size_t nblocks; \
+ unsigned i; \
+ \
+ /* Zero the counters. */ \
+ ctx->off = 0; ctx->len = 0; \
+ BLKC_ZERO(PRE, ctx->a); \
+ \
+ /* Calculate the initial counter from the nonce. */ \
+ if (nsz == PRE##_BLKSZ - 4) { \
+ /* Easy version: initialize the final word to 1 and copy the \
+ * remaining words from the nonce. (The spec shows the nonce and \
+ * counter the other way around for 64-bit block ciphers, but I'm \
+ * sure this is just a mistake.) \
+ */ \
+ \
+ for (i = 0; i < PRE##_BLKSZ/4 - 1; i++) \
+ { ctx->c0[i] = BLKC_LOAD_E(PRE)(q); q += 4; } \
+ ctx->c0[PRE##_BLKSZ/4 - 1] = BLKC_BWORD(PRE, 1); \
+ } else { \
+ /* Harder version: hash the nonce down with GHASH. */ \
+ \
+ BLKC_ZERO(PRE, ctx->c0); nblocks = 0; \
+ while (nsz >= PRE##_BLKSZ) { \
+ BLKC_XLOAD(PRE, ctx->c0, q); q += PRE##_BLKSZ; \
+ GCM_MULK(PRE, ctx->c0, ctx->k.ktab); \
+ nsz -= PRE##_BLKSZ; nblocks++; \
+ } \
+ if (nsz) { \
+ memcpy(b, q, nsz); memset(b + nsz, 0, PRE##_BLKSZ - nsz); \
+ BLKC_XLOAD(PRE, ctx->c0, b); \
+ GCM_MULK(PRE, ctx->c0, ctx->k.ktab); \
+ } \
+ gcm_ghashdone(&pre##_gcmparams, ctx->c0, ctx->k.ktab, \
+ 0, 0, nblocks, nsz); \
+ } \
+ \
+ /* We must remember the initial counter for the final tag \
+ * calculation. (I conjecture that storing the final counter instead \
+ * would be just as secure, and require less state, but I've not \
+ * proven this, and anyway it wouldn't interoperate.) Copy it to \
+ * make the working counter. \
+ */ \
+ BLKC_MOVE(PRE, ctx->c, ctx->c0); \
+} \
+ \
+/* --- @pre_gcmencrypt@ --- * \
+ * \
+ * Arguments: @pre_gcmctx *ctx@ = pointer to GCM operation context \
+ * @const void *src@ = pointer to plaintext message chunk \
+ * @size_t sz@ = size of the plaintext \
+ * @buf *dst@ = a buffer to write the ciphertext to \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Encrypts a chunk of a plaintext message, writing a \
+ * chunk of ciphertext to the output buffer and updating \
+ * the operation state. \
+ * \
+ * For GCM, we always write a ciphertext chunk the same \
+ * size as the plaintext. The messing about with @buf@ \
+ * objects makes the interface consistent with other AEAD \
+ * schemes which can't do this. \
+ */ \
+ \
+int pre##_gcmencrypt(pre##_gcmctx *ctx, \
+ const void *src, size_t sz, buf *dst) \
+{ \
+ rsvr_plan plan; \
+ uint32 t[PRE##_BLKSZ/4]; \
+ const octet *p = src; \
+ octet *q, *r, y; \
+ \
+ /* Allocate space for the ciphertext. */ \
+ if (sz) { q = buf_get(dst, sz); if (!q) return (-1); } \
+ else q = 0; \
+ \
+ /* Determine the buffering plan. Our buffer is going to do double- \
+ * duty here. The end portion is going to contain mask from the \
+ * encrypted counter which we mix into the plaintext to encrypt it; \
+ * the start portion, which originally mask bytes we've already used, \
+ * will hold the output ciphertext, which will eventually be \
+ * collected into the GHASH state. \
+ */ \
+ rsvr_mkplan(&plan, &pre##_gcmpolicy, ctx->off, sz); \
+ \
+ /* Initial portion, fulfilled from the buffer. If the buffer is \
+ * empty, then that means that we haven't yet encrypted the current \
+ * counter, so we should do that and advance it. \
+ */ \
+ if (plan.head) { \
+ if (!ctx->off) { \
+ GCM_STEP(PRE, ctx->c); pre##_eblk(&ctx->k.ctx, ctx->c, t); \
+ BLKC_STORE(PRE, ctx->b, t); \
+ } \
+ r = ctx->b + ctx->off; ctx->off += plan.head; \
+ while (plan.head--) { y = *p++ ^ *r; *r++ = *q++ = y; } \
+ } \
+ \
+ /* If we've filled up the buffer then we need to cycle the MAC and \
+ * reset the offset. \
+ */ \
+ if (plan.from_rsvr) { \
+ BLKC_XLOAD(PRE, ctx->a, ctx->b); GCM_MULK(PRE, ctx->a, ctx->k.ktab); \
+ ctx->len++; ctx->off = 0; \
+ } \
+ \
+ /* Now to process the main body of the input. */ \
+ while (plan.from_input) { \
+ GCM_STEP(PRE, ctx->c); pre##_eblk(&ctx->k.ctx, ctx->c, t); \
+ BLKC_XLOAD(PRE, t, p); p += PRE##_BLKSZ; \
+ BLKC_STORE(PRE, q, t); q += PRE##_BLKSZ; \
+ BLKC_XMOVE(PRE, ctx->a, t); GCM_MULK(PRE, ctx->a, ctx->k.ktab); \
+ plan.from_input -= PRE##_BLKSZ; ctx->len++; \
+ } \
+ \
+ /* Finally, deal with any final portion. If there is one, we know \
+ * that the buffer is empty: we must have filled it above, or this \
+ * would all count as `initial' data. \
+ */ \
+ if (plan.tail) { \
+ GCM_STEP(PRE, ctx->c); pre##_eblk(&ctx->k.ctx, ctx->c, t); \
+ BLKC_STORE(PRE, ctx->b, t); \
+ r = ctx->b; ctx->off += plan.tail; \
+ while (plan.tail--) { y = *p++ ^ *r; *r++ = *q++ = y; } \
+ } \
+ \
+ /* And we're done. */ \
+ return (0); \
+} \
+ \
+/* --- @pre_gcmdecrypt@ --- * \
+ * \
+ * Arguments: @pre_gcmctx *ctx@ = pointer to GCM operation context \
+ * @const void *src@ = pointer to ciphertext message chunk \
+ * @size_t sz@ = size of the ciphertext \
+ * @buf *dst@ = a buffer to write the plaintext to \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Decrypts a chunk of a ciphertext message, writing a \
+ * chunk of plaintext to the output buffer and updating \
+ * the operation state. \
+ * \
+ * For GCM, we always write a plaintext chunk the same \
+ * size as the ciphertext. The messing about with @buf@ \
+ * objects makes the interface consistent with other AEAD \
+ * schemes which can't do this. \
+ */ \
+ \
+int pre##_gcmdecrypt(pre##_gcmctx *ctx, \
+ const void *src, size_t sz, buf *dst) \
+{ \
+ rsvr_plan plan; \
+ uint32 t[PRE##_BLKSZ/4], u[PRE##_BLKSZ]; \
+ const octet *p = src; \
+ octet *q, *r, y; \
+ \
+ /* Allocate space for the plaintext. */ \
+ if (sz) { q = buf_get(dst, sz); if (!q) return (-1); } \
+ else q = 0; \
+ \
+ /* Determine the buffering plan. Our buffer is going to do double- \
+ * duty here. The end portion is going to contain mask from the \
+ * encrypted counter which we mix into the plaintext to encrypt it; \
+ * the start portion, which originally mask bytes we've already used, \
+ * will hold the input ciphertext, which will eventually be \
+ * collected into the GHASH state. \
+ */ \
+ rsvr_mkplan(&plan, &pre##_gcmpolicy, ctx->off, sz); \
+ \
+ /* Initial portion, fulfilled from the buffer. If the buffer is \
+ * empty, then that means that we haven't yet encrypted the current \
+ * counter, so we should do that and advance it. \
+ */ \
+ if (plan.head) { \
+ if (!ctx->off) { \
+ GCM_STEP(PRE, ctx->c); pre##_eblk(&ctx->k.ctx, ctx->c, t); \
+ BLKC_STORE(PRE, ctx->b, t); \
+ } \
+ r = ctx->b + ctx->off; ctx->off += plan.head; \
+ while (plan.head--) { y = *p++; *q++ = y ^ *r; *r++ = y; } \
+ } \
+ \
+ /* If we've filled up the buffer then we need to cycle the MAC and \
+ * reset the offset. \
+ */ \
+ if (plan.from_rsvr) { \
+ BLKC_XLOAD(PRE, ctx->a, ctx->b); GCM_MULK(PRE, ctx->a, ctx->k.ktab); \
+ ctx->len++; ctx->off = 0; \
+ } \
+ \
+ /* Now to process the main body of the input. */ \
+ while (plan.from_input) { \
+ GCM_STEP(PRE, ctx->c); pre##_eblk(&ctx->k.ctx, ctx->c, t); \
+ BLKC_LOAD(PRE, u, p); p += PRE##_BLKSZ; \
+ BLKC_XSTORE(PRE, q, t, u); q += PRE##_BLKSZ; \
+ BLKC_XMOVE(PRE, ctx->a, u); GCM_MULK(PRE, ctx->a, ctx->k.ktab); \
+ plan.from_input -= PRE##_BLKSZ; ctx->len++; \
+ } \
+ \
+ /* Finally, deal with any final portion. If there is one, we know \
+ * that the buffer is empty: we must have filled it above, or this \
+ * would all count as `initial' data. \
+ */ \
+ if (plan.tail) { \
+ GCM_STEP(PRE, ctx->c); pre##_eblk(&ctx->k.ctx, ctx->c, t); \
+ BLKC_STORE(PRE, ctx->b, t); \
+ r = ctx->b; ctx->off += plan.tail; \
+ while (plan.tail--) { y = *p++; *q++ = y ^ *r; *r++ = y; } \
+ } \
+ \
+ /* And we're done. */ \
+ return (0); \
+} \
+ \
+/* --- @pre_gcmtag@ --- * \
+ * \
+ * Arguments: @pre_gcmctx *ctx@ = pointer to an GCM context \
+ * @const pre_gcmaadctx *aad@ = pointer to AAD context, or \
+ * null \
+ * @octet *t@ = where to write a (full-length) tag \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Finishes an GCM operation, by calculating the tag. \
+ */ \
+ \
+static void pre##_gcmtag(pre##_gcmctx *ctx, \
+ const pre##_gcmaadctx *aad, octet *t) \
+{ \
+ octet b[PRE##_BLKSZ]; \
+ uint32 u[PRE##_BLKSZ/4]; \
+ unsigned long n; \
+ \
+ /* Finish tagging the ciphertext. */ \
+ if (ctx->off) { \
+ memcpy(b, ctx->b, ctx->off); \
+ memset(b + ctx->off, 0, PRE##_BLKSZ - ctx->off); \
+ BLKC_XLOAD(PRE, ctx->a, b); GCM_MULK(PRE, ctx->a, ctx->k.ktab); \
+ } \
+ \
+ /* If there's no AAD, because the pointer is null or no data was \
+ * supplied, then apply that to the GHASH state. (Otherwise there's \
+ * nothing to do here.) \
+ */ \
+ if (aad && (aad->len || aad->off)) { \
+ BLKC_MOVE(PRE, u, aad->a); \
+ if (aad->off) { \
+ memcpy(b, aad->b, aad->off); \
+ memset(b + aad->off, 0, PRE##_BLKSZ - aad->off); \
+ BLKC_XLOAD(PRE, u, b); GCM_MULK(PRE, u, ctx->k.ktab); \
+ } \
+ n = ctx->len; if (ctx->off) n++; \
+ gcm_concat(&pre##_gcmparams, ctx->a, u, ctx->k.ktab, n); \
+ } \
+ \
+ /* Finish off the hash by appending the length. */ \
+ gcm_ghashdone(&pre##_gcmparams, ctx->a, ctx->k.ktab, \
+ aad ? aad->len : 0, aad ? aad->off : 0, \
+ ctx->len, ctx->off); \
+ \
+ /* Mask the hash and store. */ \
+ pre##_eblk(&ctx->k.ctx, ctx->c0, u); \
+ BLKC_XSTORE(PRE, t, ctx->a, u); \
+} \
+ \
+/* --- @pre_gcmencryptdone@ --- * \
+ * \
+ * Arguments: @pre_gcmctx *ctx@ = pointer to an GCM context \
+ * @const pre_gcmaadctx *aad@ = pointer to AAD context, or \
+ * null \
+ * @buf *dst@ = buffer for remaining ciphertext \
+ * @void *tag@ = where to write the tag \
+ * @size_t tsz@ = length of tag to store \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Completes an GCM encryption operation. The @aad@ \
+ * pointer may be null if there is no additional \
+ * authenticated data. GCM doesn't buffer ciphertext, but \
+ * the output buffer is provided anyway for consistency \
+ * with other AEAD schemes which don't have this property; \
+ * the function will fail if the output buffer is broken. \
+ */ \
+ \
+int pre##_gcmencryptdone(pre##_gcmctx *ctx, \
+ const pre##_gcmaadctx *aad, buf *dst, \
+ void *tag, size_t tsz) \
+{ \
+ octet t[PRE##_BLKSZ]; \
+ \
+ if (tsz > PRE##_BLKSZ) return (-1); \
+ if (!BOK(dst)) return (-1); \
+ pre##_gcmtag(ctx, aad, t); memcpy(tag, t, tsz); \
+ return (0); \
+} \
+ \
+/* --- @pre_gcmdecryptdone@ --- * \
+ * \
+ * Arguments: @pre_gcmctx *ctx@ = pointer to an GCM context \
+ * @const pre_gcmaadctx *aad@ = pointer to AAD context, or \
+ * null \
+ * @buf *dst@ = buffer for remaining plaintext \
+ * @const void *tag@ = tag to verify \
+ * @size_t tsz@ = length of tag \
+ * \
+ * Returns: @+1@ for complete success; @0@ if tag verification \
+ * failed; @-1@ for other kinds of errors. \
+ * \
+ * Use: Completes an GCM decryption operation. The @aad@ \
+ * pointer may be null if there is no additional \
+ * authenticated data. GCM doesn't buffer plaintext, but \
+ * the output buffer is provided anyway for consistency \
+ * with other AEAD schemes which don't have this property; \
+ * the function will fail if the output buffer is broken. \
+ */ \
+ \
+int pre##_gcmdecryptdone(pre##_gcmctx *ctx, \
+ const pre##_gcmaadctx *aad, buf *dst, \
+ const void *tag, size_t tsz) \
+{ \
+ octet t[PRE##_BLKSZ]; \
+ \
+ if (tsz > PRE##_BLKSZ) return (-1); \
+ if (!BOK(dst)) return (-1); \
+ pre##_gcmtag(ctx, aad, t); \
+ if (!ct_memeq(tag, t, tsz)) return (0); \
+ else return (+1); \
+} \
+ \
+/* --- Generic AEAD interface --- */ \
+ \
+typedef struct gactx { \
+ gaead_aad a; \
+ pre##_gcmaadctx aad; \
+} gactx; \
+ \
+static gaead_aad *gadup(const gaead_aad *a) \
+ { gactx *aad = S_CREATE(gactx); *aad = *(gactx *)a; return (&aad->a); } \
+ \
+static void gahash(gaead_aad *a, const void *h, size_t hsz) \
+ { gactx *aad = (gactx *)a; pre##_gcmaadhash(&aad->aad, h, hsz); } \
+ \
+static void gadestroy(gaead_aad *a) \
+ { gactx *aad = (gactx *)a; BURN(*aad); S_DESTROY(aad); } \
+ \
+static const gaead_aadops gaops = \
+ { &pre##_gcm, gadup, gahash, gadestroy }; \
+ \
+static gaead_aad *gaad(const pre##_gcmkey *k) \
+{ \
+ gactx *aad = S_CREATE(gactx); \
+ aad->a.ops = &gaops; \
+ pre##_gcmaadinit(&aad->aad, k); \
+ return (&aad->a); \
+} \
+ \
+typedef struct gectx { \
+ gaead_enc e; \
+ pre##_gcmctx ctx; \
+} gectx; \
+ \
+static gaead_aad *geaad(gaead_enc *e) \
+ { gectx *enc = (gectx *)e; return (gaad(&enc->ctx.k)); } \
+ \
+static int gereinit(gaead_enc *e, const void *n, size_t nsz, \
+ size_t hsz, size_t msz, size_t tsz) \
+{ \
+ gectx *enc = (gectx *)e; \
+ \
+ if (tsz > PRE##_BLKSZ) return (-1); \
+ pre##_gcmreinit(&enc->ctx, n, nsz); \
+ return (0); \
+} \
+ \
+static int geenc(gaead_enc *e, const void *m, size_t msz, buf *b) \
+{ \
+ gectx *enc = (gectx *)e; \
+ return (pre##_gcmencrypt(&enc->ctx, m, msz, b)); \
+} \
+ \
+static int gedone(gaead_enc *e, const gaead_aad *a, \
+ buf *b, void *t, size_t tsz) \
+{ \
+ gectx *enc = (gectx *)e; gactx *aad = (gactx *)a; \
+ assert(!a || a->ops == &gaops); \
+ return (pre##_gcmencryptdone(&enc->ctx, a ? &aad->aad : 0, b, t, tsz)); \
+} \
+ \
+static void gedestroy(gaead_enc *e) \
+ { gectx *enc = (gectx *)e; BURN(*enc); S_DESTROY(enc); } \
+ \
+static const gaead_encops geops = \
+ { &pre##_gcm, geaad, gereinit, geenc, gedone, gedestroy }; \
+ \
+typedef struct gdctx { \
+ gaead_dec d; \
+ pre##_gcmctx ctx; \
+} gdctx; \
+ \
+static gaead_aad *gdaad(gaead_dec *d) \
+ { gdctx *dec = (gdctx *)d; return (gaad(&dec->ctx.k)); } \
+ \
+static int gdreinit(gaead_dec *d, const void *n, size_t nsz, \
+ size_t hsz, size_t csz, size_t tsz) \
+{ \
+ gdctx *dec = (gdctx *)d; \
+ \
+ if (tsz > PRE##_BLKSZ) return (-1); \
+ pre##_gcmreinit(&dec->ctx, n, nsz); \
+ return (0); \
+} \
+ \
+static int gddec(gaead_dec *d, const void *c, size_t csz, buf *b) \
+{ \
+ gdctx *dec = (gdctx *)d; \
+ return (pre##_gcmdecrypt(&dec->ctx, c, csz, b)); \
+} \
+ \
+static int gddone(gaead_dec *d, const gaead_aad *a, \
+ buf *b, const void *t, size_t tsz) \
+{ \
+ gdctx *dec = (gdctx *)d; gactx *aad = (gactx *)a; \
+ assert(!a || a->ops == &gaops); \
+ return (pre##_gcmdecryptdone(&dec->ctx, a ? &aad->aad : 0, b, t, tsz)); \
+} \
+ \
+static void gddestroy(gaead_dec *d) \
+ { gdctx *dec = (gdctx *)d; BURN(*dec); S_DESTROY(dec); } \
+ \
+static const gaead_decops gdops = \
+ { &pre##_gcm, gdaad, gdreinit, gddec, gddone, gddestroy }; \
+ \
+typedef struct gkctx { \
+ gaead_key k; \
+ pre##_gcmkey key; \
+} gkctx; \
+ \
+static gaead_aad *gkaad(const gaead_key *k) \
+ { gkctx *key = (gkctx *)k; return (gaad(&key->key)); } \
+ \
+static gaead_enc *gkenc(const gaead_key *k, const void *n, size_t nsz, \
+ size_t hsz, size_t msz, size_t tsz) \
+{ \
+ gkctx *key = (gkctx *)k; \
+ gectx *enc = S_CREATE(gectx); \
+ \
+ enc->e.ops = &geops; \
+ pre##_gcminit(&enc->ctx, &key->key, n, nsz); \
+ return (&enc->e); \
+} \
+ \
+static gaead_dec *gkdec(const gaead_key *k, const void *n, size_t nsz, \
+ size_t hsz, size_t csz, size_t tsz) \
+{ \
+ gkctx *key = (gkctx *)k; \
+ gdctx *dec = S_CREATE(gdctx); \
+ \
+ dec->d.ops = &gdops; \
+ pre##_gcminit(&dec->ctx, &key->key, n, nsz); \
+ return (&dec->d); \
+} \
+ \
+static void gkdestroy(gaead_key *k) \
+ { gkctx *key = (gkctx *)k; BURN(*key); S_DESTROY(key); } \
+ \
+static const gaead_keyops gkops = \
+ { &pre##_gcm, gkaad, gkenc, gkdec, gkdestroy }; \
+ \
+static gaead_key *gckey(const void *k, size_t ksz) \
+{ \
+ gkctx *key = S_CREATE(gkctx); \
+ key->k.ops = &gkops; \
+ pre##_gcmsetkey(&key->key, k, ksz); \
+ return (&key->k); \
+} \
+ \
+const gcaead pre##_gcm = { \
+ name "-gcm", \
+ pre##_keysz, pre##_gcmnoncesz, pre##_gcmtagsz, \
+ PRE##_BLKSZ, 0, 0, 0, \
+ gckey \
+}; \
+ \
+GCM_TESTX(PRE, pre, name, fname)
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#define GCM_TEST(PRE, pre) GCM_TESTX(PRE, pre, #pre, #pre)
+
+/* --- @GCM_TEST@ --- *
+ *
+ * Arguments: @PRE, pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Standard test rig for GCM functions.
+ */
+
+#ifdef TEST_RIG
+
+#include <stdio.h>
+
+#include <mLib/dstr.h>
+#include <mLib/quis.h>
+#include <mLib/testrig.h>
+
+#define GCM_TESTX(PRE, pre, name, fname) \
+ \
+static int gcmverify(dstr *v) \
+{ \
+ pre##_gcmkey key; \
+ pre##_gcmaadctx aad; \
+ pre##_gcmctx ctx; \
+ int ok = 1, win; \
+ int i; \
+ octet *p; \
+ int szs[] = { 1, 7, 192, -1, 0 }, *ip; \
+ size_t hsz, msz; \
+ dstr d = DSTR_INIT, t = DSTR_INIT; \
+ buf b; \
+ \
+ dstr_ensure(&d, v[4].len > v[3].len ? v[4].len : v[3].len); \
+ dstr_ensure(&t, v[5].len); t.len = v[5].len; \
+ \
+ pre##_gcmsetkey(&key, v[0].buf, v[0].len); \
+ \
+ for (ip = szs; *ip; ip++) { \
+ \
+ pre##_gcminit(&ctx, &key, (octet *)v[1].buf, v[1].len); \
+ \
+ i = *ip; \
+ hsz = v[2].len; \
+ if (i == -1) i = hsz; \
+ if (i > hsz) continue; \
+ p = (octet *)v[2].buf; \
+ pre##_gcmaadinit(&aad, &key); \
+ while (hsz) { \
+ if (i > hsz) i = hsz; \
+ pre##_gcmaadhash(&aad, p, i); \
+ p += i; hsz -= i; \
+ } \
+ \
+ buf_init(&b, d.buf, d.sz); \
+ i = *ip; \
+ msz = v[3].len; \
+ if (i == -1) i = msz; \
+ if (i > msz) continue; \
+ p = (octet *)v[3].buf; \
+ while (msz) { \
+ if (i > msz) i = msz; \
+ if (pre##_gcmencrypt(&ctx, p, i, &b)) { \
+ puts("!! gcmencrypt reports failure"); \
+ goto fail_enc; \
+ } \
+ p += i; msz -= i; \
+ } \
+ \
+ if (pre##_gcmencryptdone(&ctx, &aad, &b, (octet *)t.buf, t.len)) { \
+ puts("!! gcmencryptdone reports failure"); \
+ goto fail_enc; \
+ } \
+ d.len = BLEN(&b); \
+ \
+ if (d.len != v[4].len || \
+ memcmp(d.buf, v[4].buf, v[4].len) != 0 || \
+ memcmp(t.buf, v[5].buf, v[5].len) != 0) { \
+ fail_enc: \
+ printf("\nfail encrypt:\n\tstep = %i", *ip); \
+ fputs("\n\tkey = ", stdout); type_hex.dump(&v[0], stdout); \
+ fputs("\n\tnonce = ", stdout); type_hex.dump(&v[1], stdout); \
+ fputs("\n\theader = ", stdout); type_hex.dump(&v[2], stdout); \
+ fputs("\n\tmessage = ", stdout); type_hex.dump(&v[3], stdout); \
+ fputs("\n\texp ct = ", stdout); type_hex.dump(&v[4], stdout); \
+ fputs("\n\tcalc ct = ", stdout); type_hex.dump(&d, stdout); \
+ fputs("\n\texp tag = ", stdout); type_hex.dump(&v[5], stdout); \
+ fputs("\n\tcalc tag = ", stdout); type_hex.dump(&t, stdout); \
+ putchar('\n'); \
+ ok = 0; \
+ } \
+ \
+ pre##_gcminit(&ctx, &key, (octet *)v[1].buf, v[1].len); \
+ \
+ buf_init(&b, d.buf, d.sz); \
+ i = *ip; \
+ msz = v[4].len; \
+ if (i == -1) i = msz; \
+ if (i > msz) continue; \
+ p = (octet *)v[4].buf; \
+ while (msz) { \
+ if (i > msz) i = msz; \
+ if (pre##_gcmdecrypt(&ctx, p, i, &b)) { \
+ puts("!! gcmdecrypt reports failure"); \
+ win = 0; goto fail_dec; \
+ } \
+ p += i; msz -= i; \
+ } \
+ \
+ win = pre##_gcmdecryptdone(&ctx, &aad, &b, \
+ (octet *)v[5].buf, v[5].len); \
+ if (win < 0) { \
+ puts("!! gcmdecryptdone reports failure"); \
+ goto fail_dec; \
+ } \
+ d.len = BLEN(&b); \
+ \
+ if (d.len != v[3].len || !win || \
+ memcmp(d.buf, v[3].buf, v[3].len) != 0) { \
+ fail_dec: \
+ printf("\nfail decrypt:\n\tstep = %i", *ip); \
+ fputs("\n\tkey = ", stdout); type_hex.dump(&v[0], stdout); \
+ fputs("\n\tnonce = ", stdout); type_hex.dump(&v[1], stdout); \
+ fputs("\n\theader = ", stdout); type_hex.dump(&v[2], stdout); \
+ fputs("\n\tciphertext = ", stdout); type_hex.dump(&v[4], stdout); \
+ fputs("\n\texp pt = ", stdout); type_hex.dump(&v[3], stdout); \
+ fputs("\n\tcalc pt = ", stdout); type_hex.dump(&d, stdout); \
+ fputs("\n\ttag = ", stdout); type_hex.dump(&v[5], stdout); \
+ printf("\n\tverify %s", win ? "ok" : "FAILED"); \
+ putchar('\n'); \
+ ok = 0; \
+ } \
+ } \
+ \
+ dstr_destroy(&d); dstr_destroy(&t); \
+ return (ok); \
+} \
+ \
+static test_chunk aeaddefs[] = { \
+ { name "-gcm", gcmverify, \
+ { &type_hex, &type_hex, &type_hex, &type_hex, \
+ &type_hex, &type_hex, 0 } }, \
+ { 0, 0, { 0 } } \
+}; \
+ \
+int main(int argc, char *argv[]) \
+{ \
+ ego(argv[0]); \
+ test_run(argc, argv, aeaddefs, SRCDIR"/t/" fname); \
+ return (0); \
+}
+
+#else
+# define GCM_TESTX(PRE, pre, name, fname)
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
--- /dev/null
+/// -*- mode: asm; asm-comment-char: ?/ -*-
+///
+/// GCM acceleration for x86 processors
+///
+/// (c) 2018 Straylight/Edgeware
+///
+
+///----- Licensing notice ---------------------------------------------------
+///
+/// This file is part of Catacomb.
+///
+/// Catacomb is free software: you can redistribute it and/or modify it
+/// under the terms of the GNU Library General Public License as published
+/// by the Free Software Foundation; either version 2 of the License, or
+/// (at your option) any later version.
+///
+/// Catacomb is distributed in the hope that it will be useful, but
+/// WITHOUT ANY WARRANTY; without even the implied warranty of
+/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+/// Library General Public License for more details.
+///
+/// You should have received a copy of the GNU Library General Public
+/// License along with Catacomb. If not, write to the Free Software
+/// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+/// USA.
+
+///--------------------------------------------------------------------------
+/// Preliminaries.
+
+#include "config.h"
+#include "asm-common.h"
+
+ .arch .pclmul
+
+ .text
+
+///--------------------------------------------------------------------------
+/// Common register allocation.
+
+#if CPUFAM_X86
+# define A eax
+# define K edx
+#elif CPUFAM_AMD64 && ABI_SYSV
+# define A rdi
+# define K rsi
+#elif CPUFAM_AMD64 && ABI_WIN
+# define A rcx
+# define K rdx
+#endif
+
+///--------------------------------------------------------------------------
+/// Multiplication macros.
+
+ // The good news is that we have a fancy instruction to do the
+ // multiplications. The bad news is that it's not particularly well-
+ // suited to the job.
+ //
+ // For one thing, it only does a 64-bit multiplication, so in general
+ // we'll need to synthesize the full-width multiply by hand. For
+ // another thing, it doesn't help with the reduction, so we have to
+ // do that by hand too. And, finally, GCM has crazy bit ordering,
+ // and the instruction does nothing useful for that at all.
+ //
+ // Focusing on that last problem first: the bits aren't in monotonic
+ // significance order unless we permute them. If we reverse the byte
+ // order, then we'll have the bits in monotonic order, but backwards,
+ // so the degree-0 coefficient will be in the most-significant bit.
+ //
+ // This is less of a difficulty than it seems at first, because
+ // algebra. Suppose we are given u = SUM_{0<=i<n} u_i t^i and v =
+ // SUM_{0<=j<n} v_j t^j; then
+ //
+ // u v = SUM_{0<=i,j<n} u_i v_j t^{i+j}
+ //
+ // Suppose instead that we're given ũ = SUM_{0<=i<n} u_{n-i-1} t^i
+ // and ṽ = SUM_{0<=j<n} v_{n-j-1} t^j, so the bits are backwards.
+ // Then
+ //
+ // ũ ṽ = SUM_{0<=i,j<n} u_{n-i-1} v_{n-j-1} t^{i+j}
+ // = SUM_{0<=i,j<n} u_i v_j t^{2n-2-(i+j)}
+ //
+ // which is almost the bit-reversal of u v, only it's shifted right
+ // by one place. Oh, well: we'll have to shift it back later.
+ //
+ // That was important to think about, but there's not a great deal to
+ // do about it yet other than to convert what we've got from the
+ // blockcipher's byte-ordering convention to our big-endian
+ // convention. Since this depends on the blockcipher convention,
+ // we'll leave the caller to cope with this: the macros here will
+ // assume that the operands are in `register' format, which is the
+ // byte-reversal of the external representation, padded at the
+ // most-significant end except for 96-bit blocks, which are
+ // zero-padded at the least-significant end (see `mul96' for the
+ // details). In the commentary, pieces of polynomial are numbered
+ // according to the degree of the coefficients, so the unit
+ // coefficient of some polynomial a is in a_0.
+ //
+ // The commentary for `mul128' is the most detailed. The other
+ // macros assume that you've already read and understood that.
+
+.macro mul128
+ // Enter with u and v in xmm0 and xmm1 respectively; leave with z =
+ // u v in xmm0. Clobbers xmm1--xmm4.
+
+ // First for the double-precision multiplication. It's tempting to
+ // use Karatsuba's identity here, but I suspect that loses more in
+ // the shifting, bit-twiddling, and dependency chains that it gains
+ // in saving a multiplication which otherwise pipelines well.
+ // xmm0 = // (u_1; u_0)
+ // xmm1 = // (v_1; v_0)
+ movdqa xmm2, xmm1 // (v_1; v_0) again
+ movdqa xmm3, xmm0 // (u_1; u_0) again
+ movdqa xmm4, xmm0 // (u_1; u_0) yet again
+ pclmulhqlqdq xmm2, xmm0 // u_1 v_0
+ pclmullqlqdq xmm0, xmm1 // u_1 v_1
+ pclmulhqlqdq xmm3, xmm1 // u_0 v_1
+ pclmulhqhqdq xmm4, xmm1 // u_0 v_0
+
+ // Arrange the pieces to form a double-precision polynomial.
+ pxor xmm2, xmm3 // (m_1; m_0) = u_1 v_0 + u_0 v_1
+ movdqa xmm1, xmm2 // (m_1; m_0) again
+ pslldq xmm2, 8 // (0; m_1)
+ psrldq xmm1, 8 // (m_0; 0)
+ pxor xmm0, xmm2 // x_1 = u_1 v_1 + m_1
+ pxor xmm1, xmm4 // x_0 = u_0 v_0 + t^64 m_0
+
+ // Two problems remain. The first is that this product is shifted
+ // left (from GCM's backwards perspective) by one place, which is
+ // annoying. Let's take care of that now. Once this is done, we'll
+ // be properly in GCM's backwards bit-ordering, so xmm1 will hold the
+ // low half of the product and xmm0 the high half. (The following
+ // diagrams show bit 0 consistently on the right.)
+ //
+ // xmm1
+ // ,-------------.-------------.-------------.-------------.
+ // | 0 x_0-x_30 | x_31-x_62 | x_63-x_94 | x_95-x_126 |
+ // `-------------^-------------^-------------^-------------'
+ //
+ // xmm0
+ // ,-------------.-------------.-------------.-------------.
+ // | x_127-x_158 | x_159-x_190 | x_191-x_222 | x_223-x_254 |
+ // `-------------^-------------^-------------^-------------'
+ //
+ // We start by shifting each 32-bit lane right (from GCM's point of
+ // view -- physically, left) by one place, which gives us this:
+ //
+ // low (xmm3)
+ // ,-------------.-------------.-------------.-------------.
+ // | x_0-x_30 0 | x_32-x_62 0 | x_64-x_94 0 | x_96-x_126 0|
+ // `-------------^-------------^-------------^-------------'
+ //
+ // high (xmm2)
+ // ,-------------.-------------.-------------.-------------.
+ // |x_128-x_158 0|x_160-x_190 0|x_192-x_222 0|x_224-x_254 0|
+ // `-------------^-------------^-------------^-------------'
+ //
+ // but we've lost a bunch of bits. We separately shift each lane
+ // left by 31 places to give us the bits we lost.
+ //
+ // low (xmm1)
+ // ,-------------.-------------.-------------.-------------.
+ // | 0...0 | 0...0 x_31 | 0...0 x_63 | 0...0 x_95 |
+ // `-------------^-------------^-------------^-------------'
+ //
+ // high (xmm0)
+ // ,-------------.-------------.-------------.-------------.
+ // | 0...0 x_127 | 0...0 x_159 | 0...0 x_191 | 0...0 x_223 |
+ // `-------------^-------------^-------------^-------------'
+ //
+ // Which is close, but we don't get a cigar yet. To get the missing
+ // bits into position, we shift each of these right by a lane, but,
+ // alas, the x_127 falls off, so, separately, we shift the high
+ // register left by three lanes, so that everything is lined up
+ // properly when we OR them all together:
+ //
+ // low (xmm1)
+ // ,-------------.-------------.-------------.-------------.
+ // ? 0...0 x_31 | 0...0 x_63 | 0...0 x_95 | 0...0 |
+ // `-------------^-------------^-------------^-------------'
+ //
+ // wrap (xmm4)
+ // ,-------------.-------------.-------------.-------------.
+ // | 0...0 | 0...0 | 0...0 | 0...0 x_127 |
+ // `-------------^-------------^-------------^-------------'
+ //
+ // high (xmm0)
+ // ,-------------.-------------.-------------.-------------.
+ // | 0...0 x_159 | 0...0 x_191 | 0...0 x_223 | 0...0 |
+ // `-------------^-------------^-------------^-------------'
+ //
+ // The `low' and `wrap' registers (xmm1, xmm3, xmm4) then collect the
+ // low 128 coefficients, while the `high' registers (xmm0, xmm2)
+ // collect the high 127 registers, leaving a zero bit at the most
+ // significant end as we expect.
+
+ // xmm0 = // (x_7, x_6; x_5, x_4)
+ // xmm1 = // (x_3, x_2; x_1, x_0)
+ movdqa xmm3, xmm1 // (x_3, x_2; x_1, x_0) again
+ movdqa xmm2, xmm0 // (x_7, x_6; x_5, x_4) again
+ psrld xmm1, 31 // shifted left; just the carries
+ psrld xmm0, 31
+ pslld xmm3, 1 // shifted right, but dropped carries
+ pslld xmm2, 1
+ movdqa xmm4, xmm0 // another copy for the carry around
+ pslldq xmm1, 4 // move carries over
+ pslldq xmm0, 4
+ psrldq xmm4, 12 // the big carry wraps around
+ por xmm1, xmm3
+ por xmm0, xmm2 // (y_7, y_6; y_5, y_4)
+ por xmm1, xmm4 // (y_3, y_2; y_1, y_0)
+
+ // And the other problem is that the result needs to be reduced
+ // modulo p(t) = t^128 + t^7 + t^2 + t + 1. Let R = t^128 = t^7 +
+ // t^2 + t + 1 in our field. So far, we've calculated z_0 and z_1
+ // such that z_0 + z_1 R = u v using the identity R = t^128: now we
+ // must collapse the two halves of z together using the other
+ // identity R = t^7 + t^2 + t + 1.
+ //
+ // We do this by working on each 32-bit word of the high half of z
+ // separately, so consider y_i, for some 4 <= i < 8. Certainly, y_i
+ // t^{32i} = y_i R t^{32(i-4)} = (t^7 + t^2 + t + 1) y_i t^{32(i-4)},
+ // but we can't use that directly without breaking up the 32-bit word
+ // structure. Instead, we start by considering just y_i t^7
+ // t^{32(i-4)}, which again looks tricky. Now, split y_i = a_i +
+ // t^25 b_i, with deg a_i < 25; then
+ //
+ // y_i t^7 t^{32(i-4)} = a_i t^7 t^{32(i-4)} + b_i t^{32(i-3)}
+ //
+ // We can similarly decompose y_i t^2 and y_i t into a pair of 32-bit
+ // contributions to the t^{32(i-4)} and t^{32(i-3)} words, but the
+ // splits are different. This is lovely, with one small snag: when
+ // we do this to y_7, we end up with a contribution back into the
+ // t^128 coefficient word. But notice that only the low seven bits
+ // of this word are affected, so there's no knock-on contribution
+ // into the t^32 word. Therefore, if we handle the high bits of each
+ // word together, and then the low bits, everything will be fine.
+
+ // First, shift the high bits down.
+ movdqa xmm2, xmm0 // (y_7, y_6; y_5, y_4) again
+ movdqa xmm3, xmm0 // (y_7, y_6; y_5, y_4) yet again
+ movdqa xmm4, xmm0 // (y_7, y_6; y_5, y_4) again again
+ pslld xmm2, 31 // the b_i for t
+ pslld xmm3, 30 // the b_i for t^2
+ pslld xmm4, 25 // the b_i for t^7
+ pxor xmm2, xmm3 // add them all together
+ pxor xmm2, xmm4
+ movdqa xmm3, xmm2 // and a copy for later
+ psrldq xmm2, 4 // contribution into low half
+ pslldq xmm3, 12 // and high half
+ pxor xmm1, xmm2
+ pxor xmm0, xmm3
+
+ // And then shift the low bits up.
+ movdqa xmm2, xmm0
+ movdqa xmm3, xmm0
+ pxor xmm1, xmm0 // mix in the unit contribution
+ psrld xmm0, 1
+ psrld xmm2, 2
+ psrld xmm3, 7
+ pxor xmm1, xmm2 // low half, unit, and t^2 contribs
+ pxor xmm0, xmm3 // t and t^7 contribs
+ pxor xmm0, xmm1 // mix them together and we're done
+.endm
+
+.macro mul64
+ // Enter with u and v in the low halves of xmm0 and xmm1
+ // respectively; leave with z = u v in xmm0. Clobbers xmm1--xmm4.
+
+ // The multiplication is thankfully easy.
+ pclmullqlqdq xmm0, xmm1 // u v
+
+ // Shift the product up by one place. After this, we're in GCM
+ // bizarro-world.
+ movdqa xmm1, xmm0 // u v again
+ psrld xmm0, 31 // shifted left; just the carries
+ pslld xmm1, 1 // shifted right, but dropped carries
+ pslldq xmm0, 4 // move carries over
+ por xmm1, xmm0 // (y_3, y_2; y_1, y_0)
+
+ // Now we must reduce. This is essentially the same as the 128-bit
+ // case above, but mostly simpler because everything is smaller. The
+ // polynomial this time is p(t) = t^64 + t^4 + t^3 + t + 1.
+
+ // First, we must detach the top (`low'!) half of the result.
+ movdqa xmm0, xmm1 // (y_3, y_2; y_1, y_0) again
+ psrldq xmm1, 8 // (y_1, y_0; 0, 0)
+
+ // Next, shift the high bits down.
+ movdqa xmm2, xmm0 // (y_3, y_2; ?, ?) again
+ movdqa xmm3, xmm0 // (y_3, y_2; ?, ?) yet again
+ movdqa xmm4, xmm0 // (y_3, y_2; ?, ?) again again
+ pslld xmm2, 31 // b_i for t
+ pslld xmm3, 29 // b_i for t^3
+ pslld xmm4, 28 // b_i for t^4
+ pxor xmm2, xmm3 // add them all together
+ pxor xmm2, xmm4
+ movdqa xmm3, xmm2 // and a copy for later
+ movq xmm2, xmm2 // zap high half
+ pslldq xmm3, 4 // contribution into high half
+ psrldq xmm2, 4 // and low half
+ pxor xmm0, xmm3
+ pxor xmm1, xmm2
+
+ // And then shift the low bits up.
+ movdqa xmm2, xmm0
+ movdqa xmm3, xmm0
+ pxor xmm1, xmm0 // mix in the unit contribution
+ psrld xmm0, 1
+ psrld xmm2, 3
+ psrld xmm3, 4
+ pxor xmm1, xmm2 // low half, unit, and t^3 contribs
+ pxor xmm0, xmm3 // t and t^4 contribs
+ pxor xmm0, xmm1 // mix them together and we're done
+.endm
+
+.macro mul96
+ // Enter with u and v in the /high/ three words of xmm0 and xmm1
+ // respectively (and zero in the low word); leave with z = u v in the
+ // high three words of xmm0, and /junk/ in the low word. Clobbers
+ // xmm1--xmm4.
+
+ // This is an inconvenient size. There's nothing for it but to do
+ // four multiplications, as if for the 128-bit case. It's possible
+ // that there's cruft in the top 32 bits of the input registers, so
+ // shift both of them up by four bytes before we start. This will
+ // mean that the high 64 bits of the result (from GCM's viewpoint)
+ // will be zero.
+ // xmm0 = // (0, u_2; u_1, u_0)
+ // xmm1 = // (0, v_2; v_1, v_0)
+ movdqa xmm2, xmm1 // (0, v_2; v_1, v_0) again
+ movdqa xmm3, xmm0 // (0, u_2; u_1, u_0) again
+ movdqa xmm4, xmm0 // (0, u_2; u_1, u_0) yet again
+ pclmulhqlqdq xmm2, xmm0 // u_2 (v_1 t^32 + v_0) = e_0
+ pclmullqlqdq xmm0, xmm1 // u_2 v_2 = d = (0; d)
+ pclmulhqlqdq xmm3, xmm1 // v_2 (u_1 t^32 + u_0) = e_1
+ pclmulhqhqdq xmm4, xmm1 // u_0 v_0 + (u_1 v_0 + u_0 v_1) t^32
+ // + u_1 v_1 t^64 = f
+
+ // Extract the high and low halves of the 192-bit result. We don't
+ // need be too picky about the unused high words of the result
+ // registers. The answer we want is d t^128 + e t^64 + f, where e =
+ // e_0 + e_1.
+ //
+ // The place values for the two halves are (t^160, t^128; t^96, ?)
+ // and (?, t^64; t^32, 1).
+ psrldq xmm0, 8 // (d; 0) = d t^128
+ pxor xmm2, xmm3 // e = (e_0 + e_1)
+ movdqa xmm1, xmm4 // f again
+ pxor xmm0, xmm2 // d t^128 + e t^64
+ psrldq xmm2, 12 // e[31..0] t^64
+ psrldq xmm1, 4 // f[95..0]
+ pslldq xmm4, 8 // f[127..96]
+ pxor xmm1, xmm2 // low 96 bits of result
+ pxor xmm0, xmm4 // high 96 bits of result
+
+ // Next, shift everything one bit to the left to compensate for GCM's
+ // strange ordering. This will be easier if we shift up the high
+ // half by a word before we start. After this we're in GCM bizarro-
+ // world.
+ movdqa xmm3, xmm1 // low half again
+ pslldq xmm0, 4 // shift high half
+ psrld xmm1, 31 // shift low half down: just carries
+ movdqa xmm2, xmm0 // copy high half
+ pslld xmm3, 1 // shift low half down: drop carries
+ psrld xmm0, 31 // shift high half up: just carries
+ pslld xmm2, 1 // shift high half down: drop carries
+ movdqa xmm4, xmm0 // copy high carries for carry-around
+ pslldq xmm0, 4 // shift carries down
+ pslldq xmm1, 4
+ psrldq xmm4, 12 // the big carry wraps around
+ por xmm1, xmm3
+ por xmm0, xmm2
+ por xmm1, xmm4
+
+ // Finally, the reduction. This is essentially the same as the
+ // 128-bit case, except that the polynomial is p(t) = t^96 + t^10 +
+ // t^9 + t^6 + 1. The degrees are larger but not enough to cause
+ // trouble for the general approach.
+
+ // First, shift the high bits down.
+ movdqa xmm2, xmm0 // copies of the high part
+ movdqa xmm3, xmm0
+ movdqa xmm4, xmm0
+ pslld xmm2, 26 // b_i for t^6
+ pslld xmm3, 23 // b_i for t^9
+ pslld xmm4, 22 // b_i for t^10
+ pxor xmm2, xmm3 // add them all together
+ pslldq xmm1, 4 // shift low part up to match
+ pxor xmm2, xmm4
+ movdqa xmm3, xmm2 // and a copy for later
+ pslldq xmm2, 8 // contribution to high half
+ psrldq xmm3, 4 // contribution to low half
+ pxor xmm1, xmm3
+ pxor xmm0, xmm2
+
+ // And then shift the low bits up.
+ movdqa xmm2, xmm0 // copies of the high part
+ movdqa xmm3, xmm0
+ pxor xmm1, xmm0 // mix in the unit contribution
+ psrld xmm0, 6
+ psrld xmm2, 9
+ psrld xmm3, 10
+ pxor xmm1, xmm2 // low half, unit, and t^9 contribs
+ pxor xmm0, xmm3 // t^6 and t^10 contribs
+ pxor xmm0, xmm1 // mix them together and we're done
+.endm
+
+.macro mul192
+ // Enter with u and v in xmm0/xmm1 and xmm2/xmm3 respectively; leave
+ // with z = u v in xmm0/xmm1 -- the top halves of the high registers
+ // are unimportant. Clobbers xmm2--xmm7.
+
+ // Start multiplying and accumulating pieces of product.
+ // xmm0 = // (u_2; u_1)
+ // xmm1 = // (u_0; ?)
+ // xmm2 = // (v_2; v_1)
+ // xmm3 = // (v_0; ?)
+ movdqa xmm4, xmm0 // (u_2; u_1) again
+ movdqa xmm5, xmm0 // (u_2; u_1) yet again
+ movdqa xmm6, xmm0 // (u_2; u_1) again again
+ movdqa xmm7, xmm1 // (u_0; ?) again
+ punpcklqdq xmm1, xmm3 // (u_0; v_0)
+ pclmulhqhqdq xmm4, xmm2 // u_1 v_1
+ pclmullqlqdq xmm3, xmm0 // u_2 v_0
+ pclmullqhqdq xmm5, xmm2 // u_2 v_1
+ pclmulhqlqdq xmm6, xmm2 // u_1 v_2
+ pxor xmm4, xmm3 // u_2 v_0 + u_1 v_1
+ pclmullqlqdq xmm7, xmm2 // u_0 v_2
+ pxor xmm5, xmm6 // b = u_2 v_1 + u_1 v_2
+ movdqa xmm6, xmm0 // (u_2; u_1) like a bad penny
+ pxor xmm4, xmm7 // c = u_0 v_2 + u_1 v_1 + u_2 v_0
+ pclmullqlqdq xmm0, xmm2 // a = u_2 v_2
+ pclmulhqhqdq xmm6, xmm1 // u_1 v_0
+ pclmulhqlqdq xmm2, xmm1 // u_0 v_1
+ pclmullqhqdq xmm1, xmm1 // e = u_0 v_0
+ pxor xmm2, xmm6 // d = u_1 v_0 + u_0 v_1
+
+ // Next, the piecing together of the product.
+ // xmm0 = // (a_1; a_0) = a = u_2 v_2
+ // xmm5 = // (b_1; b_0) = b = u_1 v_2 + u_2 v_1
+ // xmm4 = // (c_1; c_0) = c = u_0 v_2 +
+ // u_1 v_1 + u_2 v_0
+ // xmm2 = // (d_1; d_0) = d = u_0 v_1 + u_1 v_0
+ // xmm1 = // (e_1; e_0) = e = u_0 v_0
+ // xmm3, xmm6, xmm7 spare
+ movdqa xmm3, xmm2 // (d_1; d_0) again
+ movdqa xmm6, xmm5 // (b_1; b_0) again
+ pslldq xmm2, 8 // (0; d_1)
+ psrldq xmm5, 8 // (b_0; 0)
+ psrldq xmm3, 8 // (d_0; 0)
+ pslldq xmm6, 8 // (0; b_1)
+ pxor xmm5, xmm2 // (b_0; d_1)
+ pxor xmm0, xmm6 // x_2 = (a_1; a_0 + b_1)
+ pxor xmm3, xmm1 // x_0 = (e_1 + d_0; e_0)
+ pxor xmm4, xmm5 // x_1 = (b_0 + c_1; c_0 + d_1)
+
+ // Now, shift it right (from GCM's point of view) by one bit, and try
+ // to leave the result in less random registers. After this, we'll
+ // be in GCM bizarro-world.
+ // xmm1, xmm2, xmm5, xmm6, xmm7 spare
+ movdqa xmm5, xmm0 // copy x_2
+ movdqa xmm1, xmm4 // copy x_1
+ movdqa xmm2, xmm3 // copy x_0
+ psrld xmm0, 31 // x_2 carries
+ psrld xmm4, 31 // x_1 carries
+ psrld xmm3, 31 // x_0 carries
+ pslld xmm5, 1 // x_2 shifted
+ pslld xmm1, 1 // x_1 shifted
+ pslld xmm2, 1 // x_0 shifted
+ movdqa xmm6, xmm0 // x_2 carry copy
+ movdqa xmm7, xmm4 // x_1 carry copy
+ pslldq xmm0, 4 // x_2 carry shifted
+ pslldq xmm4, 4 // x_1 carry shifted
+ pslldq xmm3, 4 // x_0 carry shifted
+ psrldq xmm6, 12 // x_2 carry out
+ psrldq xmm7, 12 // x_1 carry out
+ por xmm0, xmm5 // (y_5; y_4)
+ por xmm1, xmm4
+ por xmm2, xmm3
+ por xmm1, xmm6 // (y_3; y_2)
+ por xmm2, xmm7 // (y_1; y_0)
+
+ // Next, the reduction. Our polynomial this time is p(x) = t^192 +
+ // t^7 + t^2 + t + 1. Yes, the magic numbers are the same as the
+ // 128-bit case. I don't know why.
+
+ // First, shift the high bits down.
+ // xmm0 = // (y_5; y_4)
+ // xmm1 = // (y_3; y_2)
+ // xmm2 = // (y_1; y_0)
+ // xmm3--xmm7 spare
+ movdqa xmm3, xmm0 // (y_5; y_4) copy
+ movdqa xmm4, xmm0 // (y_5; y_4) copy
+ movdqa xmm5, xmm0 // (y_5; y_4) copy
+ pslld xmm3, 31 // (y_5; y_4) b_i for t
+ pslld xmm4, 30 // (y_5; y_4) b_i for t^2
+ pslld xmm5, 25 // (y_5; y_4) b_i for t^7
+ movq xmm6, xmm1 // (y_3; 0) copy
+ pxor xmm3, xmm4
+ movq xmm7, xmm1 // (y_3; 0) copy
+ pxor xmm3, xmm5
+ movq xmm5, xmm1 // (y_3; 0) copy
+ movdqa xmm4, xmm3 // (y_5; y_4) b_i combined
+ pslld xmm6, 31 // (y_3; 0) b_i for t
+ pslld xmm7, 30 // (y_3; 0) b_i for t^2
+ pslld xmm5, 25 // (y_3; 0) b_i for t^7
+ psrldq xmm3, 12 // (y_5; y_4) low contrib
+ pslldq xmm4, 4 // (y_5; y_4) high contrib
+ pxor xmm6, xmm7
+ pxor xmm2, xmm3
+ pxor xmm6, xmm5
+ pxor xmm1, xmm4
+ pslldq xmm6, 4
+ pxor xmm2, xmm6
+
+ // And finally shift the low bits up. Unfortunately, we also have to
+ // split the low bits out.
+ // xmm0 = // (y'_5; y'_4)
+ // xmm1 = // (y'_3; y'_2)
+ // xmm2 = // (y'_1; y'_0)
+ movdqa xmm5, xmm1 // copies of (y'_3; y'_2)
+ movdqa xmm6, xmm1
+ movdqa xmm7, xmm1
+ psrldq xmm1, 8 // bring down (y'_2; ?)
+ movdqa xmm3, xmm0 // copies of (y'_5; y'_4)
+ movdqa xmm4, xmm0
+ punpcklqdq xmm1, xmm2 // (y'_2; y'_1)
+ psrldq xmm2, 8 // (y'_0; ?)
+ pxor xmm2, xmm5 // low half and unit contrib
+ pxor xmm1, xmm0
+ psrld xmm5, 1
+ psrld xmm0, 1
+ psrld xmm6, 2
+ psrld xmm3, 2
+ psrld xmm7, 7
+ psrld xmm4, 7
+ pxor xmm2, xmm6 // low half, unit, t^2 contribs
+ pxor xmm1, xmm3
+ pxor xmm5, xmm7 // t and t^7 contribs
+ pxor xmm0, xmm4
+ pxor xmm5, xmm2 // mix everything together
+ pxor xmm0, xmm1
+ movq xmm1, xmm5 // shunt (z_0; ?) into proper place
+.endm
+
+.macro mul256
+ // Enter with u and v in xmm0/xmm1 and xmm2/xmm3 respectively; leave
+ // with z = u v in xmm0/xmm1. Clobbers xmm2--xmm7. On 32-bit x86,
+ // requires 16 bytes aligned space at SP; on amd64, also clobbers
+ // xmm8.
+
+ // Now it's starting to look worthwhile to do Karatsuba. Suppose
+ // u = u_0 + u_1 B and v = v_0 + v_1 B. Then
+ //
+ // u v = (u_0 v_0) + (u_0 v_1 + u_1 v_0) B + (u_1 v_1) B^2
+ //
+ // Name these coefficients of B^i be a, b, and c, respectively, and
+ // let r = u_0 + u_1 and s = v_0 + v_1. Then observe that
+ //
+ // q = r s = (u_0 + u_1) (v_0 + v_1)
+ // = (u_0 v_0) + (u1 v_1) + (u_0 v_1 + u_1 v_0)
+ // = a + d + c
+ //
+ // The first two terms we've already calculated; the last is the
+ // remaining one we want. We'll set B = t^128. We know how to do
+ // 128-bit multiplications already, and Karatsuba is too annoying
+ // there, so there'll be 12 multiplications altogether, rather than
+ // the 16 we'd have if we did this the naïve way.
+ //
+ // On x86, there aren't quite enough registers, so spill one for a
+ // bit. On AMD64, we can keep on going, so it's all good.
+
+ // xmm0 = // u_1 = (u_11; u_10)
+ // xmm1 = // u_0 = (u_01; u_00)
+ // xmm2 = // v_1 = (v_11; v_10)
+ // xmm3 = // v_0 = (v_01; v_00)
+ movdqa xmm4, xmm0 // u_1 again
+#if CPUFAM_X86
+ movdqa [esp + 0], xmm3
+#elif CPUFAM_AMD64
+ movdqa xmm8, xmm3
+# define V0 xmm8
+#endif
+ pxor xmm4, xmm1 // u_* = (u_01 + u_11; u_00 + u_10)
+ pxor xmm3, xmm2 // v_* = (v_01 + v_11; v_00 + v_10)
+
+ // Start by building the cross product, q = u_* v_*.
+ movdqa xmm7, xmm4 // more copies of u_*
+ movdqa xmm5, xmm4
+ movdqa xmm6, xmm4
+ pclmullqhqdq xmm4, xmm3 // u_*1 v_*0
+ pclmulhqlqdq xmm7, xmm3 // u_*0 v_*1
+ pclmullqlqdq xmm5, xmm3 // u_*1 v_*1
+ pclmulhqhqdq xmm6, xmm3 // u_*0 v_*0
+ pxor xmm4, xmm7 // u_*1 v_*0 + u_*0 v_*1
+ movdqa xmm7, xmm4
+ pslldq xmm4, 8
+ psrldq xmm7, 8
+ pxor xmm5, xmm4 // q_1
+ pxor xmm6, xmm7 // q_0
+
+ // Next, work on the high half, a = u_1 v_1.
+ movdqa xmm3, xmm0 // more copies of u_1
+ movdqa xmm4, xmm0
+ movdqa xmm7, xmm0
+ pclmullqhqdq xmm0, xmm2 // u_11 v_10
+ pclmulhqlqdq xmm3, xmm2 // u_10 v_11
+ pclmullqlqdq xmm4, xmm2 // u_11 v_11
+ pclmulhqhqdq xmm7, xmm2 // u_10 v_10
+#if CPUFAM_X86
+ movdqa xmm2, [esp + 0]
+# define V0 xmm2
+#endif
+ pxor xmm0, xmm3 // u_10 v_11 + u_11 v_10
+ movdqa xmm3, xmm0
+ pslldq xmm0, 8
+ psrldq xmm3, 8
+ pxor xmm4, xmm0 // x_1 = a_1
+ pxor xmm7, xmm3 // a_0
+
+ // Mix that into the product now forming in xmm4--xmm7.
+ pxor xmm5, xmm4 // a_1 + q_1
+ pxor xmm6, xmm7 // a_0 + q_0
+ pxor xmm5, xmm7 // a_0 + (a_1 + q_1)
+
+ // Finally, the low half, c = u_0 v_0.
+ movdqa xmm0, xmm1 // more copies of u_0
+ movdqa xmm3, xmm1
+ movdqa xmm7, xmm1
+ pclmullqhqdq xmm1, V0 // u_01 v_00
+ pclmulhqlqdq xmm0, V0 // u_00 v_01
+ pclmullqlqdq xmm3, V0 // u_01 v_01
+ pclmulhqhqdq xmm7, V0 // u_00 v_00
+ pxor xmm0, xmm1 // u_10 v_11 + u_11 v_10
+ movdqa xmm1, xmm0
+ pslldq xmm0, 8
+ psrldq xmm1, 8
+ pxor xmm3, xmm0 // c_1
+ pxor xmm7, xmm1 // x_0 = c_0
+
+ // And mix that in to complete the product.
+ pxor xmm6, xmm3 // (a_0 + q_0) + c_1
+ pxor xmm5, xmm3 // x_2 = a_0 + (a_1 + c_1 + q_1) = a_0 + b_1
+ pxor xmm6, xmm7 // x_1 = (a_0 + c_0 + q_0) + c_1 = b_0 + c_1
+
+#undef V0
+
+ // Now we need to shift that whole lot one bit to the left. This
+ // will also give us an opportunity to put the product back in
+ // xmm0--xmm3. This is a slightly merry dance because it's nearly
+ // pipelined but we don't have enough registers.
+ //
+ // After this, we'll be in GCM bizarro-world.
+ movdqa xmm0, xmm4 // x_3 again
+ psrld xmm4, 31 // x_3 carries
+ pslld xmm0, 1 // x_3 shifted left
+ movdqa xmm3, xmm4 // x_3 copy carries
+ movdqa xmm1, xmm5 // x_2 again
+ pslldq xmm4, 4 // x_3 carries shifted up
+ psrld xmm5, 31 // x_2 carries
+ psrldq xmm3, 12 // x_3 big carry out
+ pslld xmm1, 1 // x_2 shifted left
+ por xmm0, xmm4 // x_3 mixed together
+ movdqa xmm4, xmm5 // x_2 copy carries
+ movdqa xmm2, xmm6 // x_1 again
+ pslldq xmm5, 4 // x_2 carries shifted up
+ psrld xmm6, 31 // x_1 carries
+ psrldq xmm4, 12 // x_2 big carry out
+ pslld xmm2, 1 // x_1 shifted
+ por xmm1, xmm5 // x_2 mixed together
+ movdqa xmm5, xmm6 // x_1 copy carries
+ por xmm1, xmm3 // x_2 with carry from x_3
+ movdqa xmm3, xmm7 // x_0 again
+ pslldq xmm6, 4 // x_1 carries shifted up
+ psrld xmm7, 31 // x_2 carries
+ psrldq xmm5, 12 // x_1 big carry out
+ pslld xmm3, 1 // x_0 shifted
+ por xmm2, xmm6 // x_1 mixed together
+ pslldq xmm7, 4 // x_0 carries shifted up
+ por xmm2, xmm4 // x_1 with carry from x_2
+ por xmm3, xmm7 // x_0 mixed together
+ por xmm3, xmm5 // x_0 with carry from x_1
+
+ // Now we must reduce. This is essentially the same as the 128-bit
+ // case above, but more complicated because everything is bigger.
+ // The polynomial this time is p(t) = t^256 + t^10 + t^5 + t^2 + 1.
+
+ // First, shift the high bits down.
+ movdqa xmm4, xmm0 // y_3 again
+ movdqa xmm5, xmm0 // y_3 yet again
+ movdqa xmm6, xmm0 // y_3 again again
+ pslld xmm4, 30 // y_3: b_i for t^2
+ pslld xmm5, 27 // y_3: b_i for t^5
+ pslld xmm6, 22 // y_3: b_i for t^10
+ movdqa xmm7, xmm1 // y_2 again
+ pxor xmm4, xmm5
+ movdqa xmm5, xmm1 // y_2 again
+ pxor xmm4, xmm6
+ movdqa xmm6, xmm1 // y_2 again
+ pslld xmm7, 30 // y_2: b_i for t^2
+ pslld xmm5, 27 // y_2: b_i for t^5
+ pslld xmm6, 22 // y_2: b_i for t^10
+ pxor xmm7, xmm5
+ movdqa xmm5, xmm4
+ pxor xmm7, xmm6
+ psrldq xmm4, 4
+ movdqa xmm6, xmm7
+ pslldq xmm5, 12
+ psrldq xmm7, 4
+ pxor xmm2, xmm4
+ pslldq xmm6, 12
+ pxor xmm3, xmm7
+ pxor xmm1, xmm5
+ pxor xmm2, xmm6
+
+ // And then shift the low bits up.
+ movdqa xmm4, xmm0 // y_3 again
+ movdqa xmm5, xmm1 // y_2 again
+ movdqa xmm6, xmm0 // y_3 yet again
+ movdqa xmm7, xmm1 // y_2 yet again
+ pxor xmm2, xmm0 // y_1 and unit contrib from y_3
+ pxor xmm3, xmm1 // y_0 and unit contrib from y_2
+ psrld xmm0, 2
+ psrld xmm1, 2
+ psrld xmm4, 5
+ psrld xmm5, 5
+ psrld xmm6, 10
+ psrld xmm7, 10
+ pxor xmm0, xmm2 // y_1, with y_3 units and t^2
+ pxor xmm1, xmm3 // y_0, with y_2 units and t^2
+ pxor xmm4, xmm6 // y_3 t^5 and t^10 contribs
+ pxor xmm5, xmm7 // y_2 t^5 and t^10 contribs
+ pxor xmm0, xmm4 // high half of reduced result
+ pxor xmm1, xmm5 // low half; all done
+.endm
+
+///--------------------------------------------------------------------------
+/// Main code.
+
+// There are a number of representations of field elements in this code and
+// it can be confusing.
+//
+// * The `external format' consists of a sequence of contiguous bytes in
+// memory called a `block'. The GCM spec explains how to interpret this
+// block as an element of a finite field. As discussed extensively, this
+// representation is very annoying for a number of reasons. On the other
+// hand, this code never actually deals with it directly.
+//
+// * The `register format' consists of one or more XMM registers, depending
+// on the block size. The bytes in these registers are in reverse order
+// -- so the least-significant byte of the lowest-numbered register holds
+// the /last/ byte in the block. If the block size is not a multiple of
+// 16 bytes, then there must be padding. 96-bit blocks are weird: the
+// padding is inserted at the /least/ significant end, so the register
+// holds (0, x_0; x_1, x_2); otherwise, the padding goes at the most
+// significant end.
+//
+// * The `words' format consists of a sequence of bytes, as in the
+// `external format', but, according to the blockcipher in use, the bytes
+// within each 32-bit word may be reversed (`big-endian') or not
+// (`little-endian'). Accordingly, there are separate entry points for
+// each variant, identified with `b' or `l'.
+
+#define SSEFUNC(f) \
+ FUNC(f##_avx); vzeroupper; endprologue; ENDFUNC; \
+ FUNC(f)
+
+SSEFUNC(gcm_mulk_128b_x86ish_pclmul)
+ // On entry, A points to a 128-bit field element in big-endian words
+ // format; K points to a field-element in register format. On exit,
+ // A is updated with the product A K.
+
+#if CPUFAM_X86
+ mov A, [esp + 4]
+ mov K, [esp + 8]
+#endif
+ endprologue
+ movdqu xmm0, [A]
+ movdqu xmm1, [K]
+ pshufd xmm0, xmm0, SHUF(3, 2, 1, 0)
+ mul128
+ pshufd xmm0, xmm0, SHUF(3, 2, 1, 0)
+ movdqu [A], xmm0
+ ret
+ENDFUNC
+
+SSEFUNC(gcm_mulk_128l_x86ish_pclmul)
+ // On entry, A points to a 128-bit field element in little-endian
+ // words format; K points to a field-element in register format. On
+ // exit, A is updated with the product A K.
+
+#if CPUFAM_X86
+ mov A, [esp + 4]
+ mov K, [esp + 8]
+ ldgot ecx
+#endif
+ endprologue
+ movdqa xmm7, [INTADDR(swaptab_128l, ecx)]
+ movdqu xmm0, [A]
+ movdqu xmm1, [K]
+ pshufb xmm0, xmm7
+ mul128
+ pshufb xmm0, xmm7
+ movdqu [A], xmm0
+ ret
+ENDFUNC
+
+SSEFUNC(gcm_mulk_64b_x86ish_pclmul)
+ // On entry, A points to a 64-bit field element in big-endian words
+ // format; K points to a field-element in register format. On exit,
+ // A is updated with the product A K.
+
+#if CPUFAM_X86
+ mov A, [esp + 4]
+ mov K, [esp + 8]
+#endif
+ endprologue
+ movq xmm0, [A]
+ movq xmm1, [K]
+ pshufd xmm0, xmm0, SHUF(1, 0, 3, 3)
+ mul64
+ pshufd xmm0, xmm0, SHUF(1, 0, 3, 3)
+ movq [A], xmm0
+ ret
+ENDFUNC
+
+SSEFUNC(gcm_mulk_64l_x86ish_pclmul)
+ // On entry, A points to a 64-bit field element in little-endian
+ // words format; K points to a field-element in register format. On
+ // exit, A is updated with the product A K.
+
+#if CPUFAM_X86
+ mov A, [esp + 4]
+ mov K, [esp + 8]
+ ldgot ecx
+#endif
+ endprologue
+ movdqa xmm7, [INTADDR(swaptab_64l, ecx)]
+ movq xmm0, [A]
+ movq xmm1, [K]
+ pshufb xmm0, xmm7
+ mul64
+ pshufb xmm0, xmm7
+ movq [A], xmm0
+ ret
+ENDFUNC
+
+SSEFUNC(gcm_mulk_96b_x86ish_pclmul)
+ // On entry, A points to a 96-bit field element in big-endian words
+ // format; K points to a field-element in register format (i.e., 16
+ // bytes, with the first four bytes zero). On exit, A is updated
+ // with the product A K.
+
+#if CPUFAM_X86
+ mov A, [esp + 4]
+ mov K, [esp + 8]
+#endif
+ endprologue
+ movq xmm0, [A + 0]
+ movd xmm2, [A + 8]
+ movdqu xmm1, [K]
+ punpcklqdq xmm0, xmm2
+ pshufd xmm0, xmm0, SHUF(3, 2, 1, 0)
+ mul96
+ pshufd xmm1, xmm0, SHUF(3, 2, 1, 0)
+ psrldq xmm0, 4
+ movq [A + 0], xmm1
+ movd [A + 8], xmm0
+ ret
+ENDFUNC
+
+SSEFUNC(gcm_mulk_96l_x86ish_pclmul)
+ // On entry, A points to a 96-bit field element in little-endian
+ // words format; K points to a field-element in register format
+ // (i.e., 16 bytes, with the first four bytes zero). On exit, A is
+ // updated with the product A K.
+
+#if CPUFAM_X86
+ mov A, [esp + 4]
+ mov K, [esp + 8]
+ ldgot ecx
+#endif
+ endprologue
+ movdqa xmm7, [INTADDR(swaptab_128l, ecx)]
+ movq xmm0, [A + 0]
+ movd xmm2, [A + 8]
+ movdqu xmm1, [K]
+ punpcklqdq xmm0, xmm2
+ pshufb xmm0, xmm7
+ mul96
+ pshufb xmm0, xmm7
+ movq [A + 0], xmm0
+ psrldq xmm0, 8
+ movd [A + 8], xmm0
+ ret
+ENDFUNC
+
+SSEFUNC(gcm_mulk_192b_x86ish_pclmul)
+ // On entry, A points to a 192-bit field element in big-endian words
+ // format; K points to a field-element in register format. On exit,
+ // A is updated with the product A K.
+
+#if CPUFAM_X86
+ mov A, [esp + 4]
+ mov K, [esp + 8]
+#endif
+#if CPUFAM_AMD64 && ABI_WIN
+ stalloc 2*16 + 8
+ savexmm xmm6, 0
+ savexmm xmm7, 16
+#endif
+ endprologue
+ movdqu xmm0, [A + 8]
+ movq xmm1, [A + 0]
+ movdqu xmm2, [K + 0]
+ movq xmm3, [K + 16]
+ pshufd xmm0, xmm0, SHUF(3, 2, 1, 0)
+ pshufd xmm1, xmm1, SHUF(1, 0, 3, 3)
+ mul192
+ pshufd xmm0, xmm0, SHUF(3, 2, 1, 0)
+ pshufd xmm1, xmm1, SHUF(1, 0, 3, 3)
+ movdqu [A + 8], xmm0
+ movq [A + 0], xmm1
+#if CPUFAM_AMD64 && ABI_WIN
+ rstrxmm xmm6, 0
+ rstrxmm xmm7, 16
+ stfree 2*16 + 8
+#endif
+ ret
+ENDFUNC
+
+SSEFUNC(gcm_mulk_192l_x86ish_pclmul)
+ // On entry, A points to a 192-bit field element in little-endian
+ // words format; K points to a field-element in register format. On
+ // exit, A is updated with the product A K.
+
+#if CPUFAM_X86
+ mov A, [esp + 4]
+ mov K, [esp + 8]
+ ldgot ecx
+#endif
+#if CPUFAM_AMD64 && ABI_WIN
+ stalloc 2*16 + 8
+ savexmm xmm6, 0
+ savexmm xmm7, 16
+#endif
+ endprologue
+ movdqu xmm0, [A + 8]
+ movq xmm1, [A + 0]
+ movdqu xmm2, [K + 0]
+ movq xmm3, [K + 16]
+ pshufb xmm0, [INTADDR(swaptab_128l, ecx)]
+ pshufb xmm1, [INTADDR(swaptab_64l, ecx)]
+ mul192
+ pshufb xmm0, [INTADDR(swaptab_128l, ecx)]
+ pshufb xmm1, [INTADDR(swaptab_64l, ecx)]
+ movdqu [A + 8], xmm0
+ movq [A + 0], xmm1
+#if CPUFAM_AMD64 && ABI_WIN
+ rstrxmm xmm6, 0
+ rstrxmm xmm7, 16
+ stfree 2*16 + 8
+#endif
+ ret
+ENDFUNC
+
+SSEFUNC(gcm_mulk_256b_x86ish_pclmul)
+ // On entry, A points to a 256-bit field element in big-endian words
+ // format; K points to a field-element in register format. On exit,
+ // A is updated with the product A K.
+
+#if CPUFAM_X86
+ pushreg ebp
+ setfp
+ mov A, [esp + 8]
+ mov K, [esp + 12]
+ and esp, ~15
+ sub esp, 16
+#endif
+#if CPUFAM_AMD64 && ABI_WIN
+ stalloc 3*16 + 8
+ savexmm xmm6, 0
+ savexmm xmm7, 16
+ savexmm xmm8, 32
+#endif
+ endprologue
+ movdqu xmm0, [A + 16]
+ movdqu xmm1, [A + 0]
+ movdqu xmm2, [K + 0]
+ movdqu xmm3, [K + 16]
+ pshufd xmm0, xmm0, SHUF(3, 2, 1, 0)
+ pshufd xmm1, xmm1, SHUF(3, 2, 1, 0)
+ mul256
+ pshufd xmm0, xmm0, SHUF(3, 2, 1, 0)
+ pshufd xmm1, xmm1, SHUF(3, 2, 1, 0)
+ movdqu [A + 16], xmm0
+ movdqu [A + 0], xmm1
+#if CPUFAM_X86
+ dropfp
+ popreg ebp
+#endif
+#if CPUFAM_AMD64 && ABI_WIN
+ rstrxmm xmm6, 0
+ rstrxmm xmm7, 16
+ rstrxmm xmm8, 32
+ stfree 3*16 + 8
+#endif
+ ret
+ENDFUNC
+
+SSEFUNC(gcm_mulk_256l_x86ish_pclmul)
+ // On entry, A points to a 256-bit field element in little-endian
+ // words format; K points to a field-element in register format. On
+ // exit, A is updated with the product A K.
+
+#if CPUFAM_X86
+ pushreg ebp
+ setfp
+ mov A, [esp + 8]
+ mov K, [esp + 12]
+ and esp, ~15
+ ldgot ecx
+ sub esp, 16
+#endif
+#if CPUFAM_AMD64 && ABI_WIN
+ stalloc 3*16 + 8
+ savexmm xmm6, 0
+ savexmm xmm7, 16
+ savexmm xmm8, 32
+#endif
+ endprologue
+ movdqa xmm7, [INTADDR(swaptab_128l, ecx)]
+ movdqu xmm0, [A + 16]
+ movdqu xmm1, [A + 0]
+ movdqu xmm2, [K + 0]
+ movdqu xmm3, [K + 16]
+ pshufb xmm0, xmm7
+ pshufb xmm1, xmm7
+ mul256
+ movdqa xmm7, [INTADDR(swaptab_128l, ecx)]
+ pshufb xmm0, xmm7
+ pshufb xmm1, xmm7
+ movdqu [A + 16], xmm0
+ movdqu [A + 0], xmm1
+#if CPUFAM_X86
+ dropfp
+ popreg ebp
+#endif
+#if CPUFAM_AMD64 && ABI_WIN
+ rstrxmm xmm6, 0
+ rstrxmm xmm7, 16
+ rstrxmm xmm8, 32
+ stfree 3*16 + 8
+#endif
+ ret
+ENDFUNC
+
+ RODATA
+
+ .balign 16
+swaptab_128l:
+ // Table for byte-swapping little-endian words-format blocks larger
+ // than 64 bits.
+ .byte 15, 14, 13, 12, 11, 10, 9, 8
+ .byte 7, 6, 5, 4, 3, 2, 1, 0
+
+ .balign 16
+swaptab_64l:
+ // Table for byte-swapping 64-bit little-endian words-format blocks.
+ .byte 7, 6, 5, 4, 3, 2, 1, 0
+ .byte 255, 255, 255, 255, 255, 255, 255, 255
+
+///----- That's all, folks --------------------------------------------------
--- /dev/null
+/* -*-c-*-
+ *
+ * The GCM authenticated encryption mode
+ *
+ * (c) 2017 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "config.h"
+
+#include <stdio.h>
+
+#include <mLib/bits.h>
+
+#include "dispatch.h"
+#include "gcm.h"
+#include "gcm-def.h"
+
+/*----- Overall strategy --------------------------------------------------*
+ *
+ * GCM is pretty awful to implement in software. (This presentation is going
+ * to be somewhat different to that in the specification, but I think it
+ * makes more sense like this.)
+ *
+ * We're given a %$w$%-bit blockcipher %$E$% with a key %$K$%.
+ *
+ * The main part is arithmetic in the finite field %$k = \gf{2^w}$%, which we
+ * represent as the quotient ring %$\gf{2}[t]/(p_w(t))$% for some irreducible
+ * degree-%$w$% polynomial %$p(t)$%, whose precise value isn't very important
+ * right now. We choose a secret point %$x = E_K(0^w)$%.
+ *
+ * We choose a length size %$z$% as follows: if %$w < 96%$ then %$z = w$%;
+ * otherwise %$z = w/2$%. Format a message pair as follows:
+ *
+ * %$F(a, b) = P_w(a) \cat P_w(b) \cat [\ell(a)]_z \cat [\ell(b)]_z$%
+ *
+ * where %$P_w(x) = x \cat 0^n$% where $%0 \le n < w$% such that
+ * %$\ell(x) + n \equiv 0 \pmod{w}$%.
+ *
+ * Hash a (block-aligned) message %$u$% as follows. First, split %$u$% into
+ * %$w$%-bit blocks %$u_0$%, %$u_1$%, %%\ldots%%, %$u_{n-1}$%. Interpret
+ * these as elements of %$k$%. Then
+ *
+ * %$G_x(u) = u_0 t^n + u_1 t^{n-1} + \cdots + u_{n-1} t$%
+ *
+ * converted back to a %$w$%-bit string.
+ *
+ * We're ready to go now. Suppose we're to encrypt a message %$M$% with
+ * header %$H$% and nonce %$N$%. If %$\ell(N) + 32 = w$% then let
+ * %$N' = N$% and let %$i_0 = 1$%; otherwise, let %$U = G_t(F(\epsilon, N))$%
+ * and split this into %$N' = U[0 \bitsto w - 32]$% and
+ * %$[i_0]_{32} = U[w - 32 \bitsto w]$%.
+ *
+ * Let %$n = \lceil \ell(M)/w \rceil$%. Compute
+ *
+ * %$y_j = E_K(N' \cat [i_0 + j]_{32})$%
+ *
+ * for %$0 \le j \le n$%. Let
+ *
+ * %$s = (y_1 \cat y_2 \cat \cdots \cat y_n)[0 \bitsto \ell(M)$%
+ *
+ * Let %$C = M \xor s$% and let %$T = G_x(F(H, C)) \xor y_0$%. These are the
+ * ciphertext and tag respectively.
+ *
+ * So why is this awful?
+ *
+ * For one thing, the bits are in a completely terrible order. The bytes are
+ * arranged in little-endian order, so the unit coefficient is in the first
+ * byte, and the degree-127 coefficient is in the last byte. But within each
+ * byte, the lowest-degree coefficient is in the most significant bit. It's
+ * therefore better to think of GCM as using a big-endian byte-ordering
+ * convention, but with the bits backwards.
+ *
+ * But messing about with byte ordering is expensive, so let's not do that in
+ * the inner loop. But multiplication in %$k$% is not easy either. Some
+ * kind of precomputed table would be nice, but that will leak secrets
+ * through the cache.
+ *
+ * I choose a particularly simple table: given %$x$%, let %$X[i'] = x t^i$%.
+ * Then $%$x y = \sum_{0\le i<w} y_i X[i']$% which is just a bunch of
+ * bitmasking. But the natural order for examining bits of %$y$% is not
+ * necessarily the obvious one. We'll have already loaded %$y$% into
+ * internal form, as 32-bit words. The good order to process these is left
+ * to right, from high to low bits. But now the order of degrees depends on
+ * the endianness of our conversion of bytes to words. Oh, well.
+ *
+ * If we've adopted a big-endian convention, then we'll see the degrees in
+ * order, 0, 1, ..., all the way up to %$w - 1$% and everything is fine. If
+ * we've adopted a little-endian convention, though, we'll see an ordering
+ * like this:
+ *
+ * 24, 25, ..., 31, 16, 17, ..., 23, 8, 9, ..., 15, 0, 1, ..., 7,
+ * 56, 57, ..., 63, 48, 49, ..., 55, 40, 41, ..., 47, 32, 33, ..., 39,
+ * etc.
+ *
+ * which is the ordinary order with 0x18 = 24 XORed into the index. That is,
+ * %$i' = i$% if we've adopted a big-endian convention, and
+ * %$i' = i \xor 24$% if we've adopted a little-endian convention.
+ */
+
+/*----- Low-level utilities -----------------------------------------------*/
+
+/* --- @mult@ --- *
+ *
+ * Arguments: @const gcm_params *p@ = pointer to the parameters
+ * @uint32 *z@ = where to write the result
+ * @const uint32 *x@ = input field element
+ *
+ * Returns: ---
+ *
+ * Use: Multiply the input field element by %$t$%, and write the
+ * product to @z@. It's safe for @x@ and @z@ to be equal, but
+ * they should not otherwise overlap. Both input and output are
+ * in big-endian form, i.e., with the lowest-degree coefficients
+ * in the most significant bits.
+ */
+
+static void mult(const gcm_params *p, uint32 *z, const uint32 *x)
+{
+ uint32 m, c, t;
+ unsigned i;
+
+ t = x[p->n - 1]; m = -(t&1u); c = m&p->poly;
+ for (i = 0; i < p->n; i++) { t = x[i]; z[i] = (t >> 1) ^ c; c = t << 31; }
+}
+
+/* --- @mul@ --- *
+ *
+ * Arguments: @const gcm_params *p@ = pointer to the parameters
+ * @uint32 *z@ = where to write the result
+ * @const uint32 *x, *y@ = input field elements
+ *
+ * Returns: ---
+ *
+ * Use: Multiply the input field elements together, and write the
+ * product to @z@. It's safe for the operands to overlap. Both
+ * inputs and the output are in big-endian form, i.e., with the
+ * lowest-degree coefficients in the most significant bits.
+ */
+
+static void mul(const gcm_params *p, uint32 *z,
+ const uint32 *x, const uint32 *y)
+{
+ uint32 m, t, u[GCM_NMAX], v[GCM_NMAX];
+ unsigned i, j, k;
+
+ /* We can't do this in-place at all, so use temporary space. Make a copy
+ * of @x@ in @u@, where we can clobber it, and build the product in @v@.
+ */
+ for (i = 0; i < p->n; i++) { u[i] = x[i]; v[i] = 0; }
+
+ /* Repeatedly multiply @x@ (in @u@) by %$t$%, and add together those
+ * %$x t^i$% selected by the bits of @y@. This is basically what you get
+ * by streaming the result of @gcm_mktable@ into @gcm_mulk_...@.
+ */
+ for (i = 0; i < p->n; i++) {
+ t = y[i];
+ for (j = 0; j < 32; j++) {
+ m = -((t >> 31)&1u);
+ for (k = 0; k < p->n; k++) v[k] ^= u[k]&m;
+ mult(p, u, u); t <<= 1;
+ }
+ }
+
+ /* Write out the result now that it's ready. */
+ for (i = 0; i < p->n; i++) z[i] = v[i];
+}
+
+/*----- Table-based multiplication ----------------------------------------*/
+
+/* --- @gcm_mktable@ --- *
+ *
+ * Arguments: @const gcm_params *p@ = pointer to the parameters
+ * @uint32 *ktab@ = where to write the table; there must be
+ * space for %$32 n$% $%n$%-word entries, i.e.,
+ * %$32 n^2$% 32-bit words in total, where %$n$% is
+ * @p->n@, the block size in words
+ * @const uint32 *k@ = input field element
+ *
+ * Returns: ---
+ *
+ * Use: Construct a table for use by @gcm_mulk_...@ below, to
+ * multiply (vaguely) efficiently by @k@.
+ */
+
+static void simple_mktable(const gcm_params *p,
+ uint32 *ktab, const uint32 *k)
+{
+ unsigned m = (p->f&GCMF_SWAP ? 0x18 : 0);
+ unsigned i, j, o = m*p->n;
+
+ /* As described above, the table stores entries %$K[i \xor m] = k t^i$%,
+ * where %$m = 0$% (big-endian cipher) or %$m = 24$% (little-endian).
+ * The first job is to store %$K[m] = k$%.
+ *
+ * We initially build the table with the entries in big-endian order, and
+ * then swap them if necessary. This makes the arithmetic functions more
+ * amenable for use by @gcm_concat@ below.
+ */
+ if (!(p->f&GCMF_SWAP)) for (i = 0; i < p->n; i++) ktab[o + i] = k[i];
+ else for (i = 0; i < p->n; i++) ktab[o + i] = ENDSWAP32(k[i]);
+
+ /* Fill in the rest of the table by repeatedly multiplying the previous
+ * entry by %$t$%.
+ */
+ for (i = 1; i < 32*p->n; i++)
+ { j = (i ^ m)*p->n; mult(p, ktab + j, ktab + o); o = j; }
+
+ /* Finally, if the cipher uses a little-endian convention, then swap all of
+ * the individual words.
+ */
+ if (p->f&GCMF_SWAP)
+ for (i = 0; i < 32*p->n*p->n; i++) ktab[i] = ENDSWAP32(ktab[i]);
+}
+
+#if CPUFAM_X86 || CPUFAM_AMD64
+static void pclmul_mktable(const gcm_params *p,
+ uint32 *ktab, const uint32 *k)
+{
+ unsigned n = p->n;
+ unsigned nz;
+ uint32 *t;
+
+ /* We just need to store the value in a way which is convenient for the
+ * assembler code to read back. That involves reordering the words, and,
+ * in the case of 96-bit blocks, padding with zeroes to fill out a 128-bit
+ * chunk.
+ */
+
+ if (n == 3) nz = 1;
+ else nz = 0;
+ t = ktab + n + nz;
+
+ if (p->f&GCMF_SWAP) while (n--) { *--t = ENDSWAP32(*k); k++; }
+ else while (n--) *--t = *k++;
+ while (nz--) *--t = 0;
+}
+#endif
+
+#if CPUFAM_ARMEL
+static void arm_crypto_mktable(const gcm_params *p,
+ uint32 *ktab, const uint32 *k)
+{
+ unsigned n = p->n;
+ uint32 *t;
+
+ /* We just need to store the value in a way which is convenient for the
+ * assembler code to read back. That involves swapping the bytes in each
+ * 64-bit lane.
+ */
+
+ t = ktab;
+ if (p->f&GCMF_SWAP) {
+ while (n >= 2) {
+ t[1] = ENDSWAP32(k[0]); t[0] = ENDSWAP32(k[1]);
+ t += 2; k += 2; n -= 2;
+ }
+ if (n) { t[1] = ENDSWAP32(k[0]); t[0] = 0; }
+ } else {
+ while (n >= 2) {
+ t[1] = k[0]; t[0] = k[1];
+ t += 2; k += 2; n -= 2;
+ }
+ if (n) { t[1] = k[0]; t[0] = 0; }
+ }
+}
+#endif
+
+#if CPUFAM_ARM64
+static uint32 rbit32(uint32 x)
+{
+ uint32 z, t;
+
+#if GCC_VERSION_P(4, 3)
+ /* Two tricks here. Firstly, two separate steps, rather than a single
+ * block of assembler, to allow finer-grained instruction scheduling.
+ * Secondly, use `ENDSWAP32' so that the compiler can cancel it if the
+ * caller actually wants the bytes reordered.
+ */
+ __asm__("rbit %w0, %w1" : "=r"(t) : "r"(x));
+ z = ENDSWAP32(t);
+#else
+ /* A generic but slightly clever implementation. */
+# define SWIZZLE(x, m, s) ((((x)&(m)) << (s)) | (((x)&~(m)) >> (s)))
+ /* 76543210 */
+ t = SWIZZLE(x, 0x0f0f0f0f, 4); /* 32107654 -- swap nibbles */
+ t = SWIZZLE(t, 0x33333333, 2); /* 10325476 -- swap bit pairs */
+ z = SWIZZLE(t, 0x55555555, 1); /* 01234567 -- swap adjacent bits */
+# undef SWIZZLE
+#endif
+ return (z);
+}
+
+static void arm64_pmull_mktable(const gcm_params *p,
+ uint32 *ktab, const uint32 *k)
+{
+ unsigned n = p->n;
+ uint32 *t;
+
+ /* We just need to store the value in a way which is convenient for the
+ * assembler code to read back. That involves two transformations:
+ *
+ * * firstly, reversing the order of the bits in each byte; and,
+ *
+ * * secondly, storing two copies of each 64-bit chunk.
+ *
+ * Note that, in this case, we /want/ the little-endian byte order of GCM,
+ * so endianness-swapping happens in the big-endian case.
+ */
+
+ t = ktab;
+ if (p->f&GCMF_SWAP) {
+ while (n >= 2) {
+ t[0] = t[2] = rbit32(k[0]);
+ t[1] = t[3] = rbit32(k[1]);
+ t += 4; k += 2; n -= 2;
+ }
+ if (n) { t[0] = t[2] = rbit32(k[0]); t[1] = t[3] = 0; }
+ } else {
+ while (n >= 2) {
+ t[0] = t[2] = ENDSWAP32(rbit32(k[0]));
+ t[1] = t[3] = ENDSWAP32(rbit32(k[1]));
+ t += 4; k += 2; n -= 2;
+ }
+ if (n) { t[0] = t[2] = ENDSWAP32(rbit32(k[0])); t[1] = t[3] = 0; }
+ }
+}
+#endif
+
+CPU_DISPATCH(EMPTY, EMPTY, void, gcm_mktable,
+ (const gcm_params *p, uint32 *ktab, const uint32 *k),
+ (p, ktab, k),
+ pick_mktable, simple_mktable)
+
+static gcm_mktable__functype *pick_mktable(void)
+{
+#if CPUFAM_X86 || CPUFAM_AMD64
+ DISPATCH_PICK_COND(gcm_mktable, pclmul_mktable,
+ cpu_feature_p(CPUFEAT_X86_SSSE3) &&
+ cpu_feature_p(CPUFEAT_X86_PCLMUL));
+#endif
+#if CPUFAM_ARMEL
+ DISPATCH_PICK_COND(gcm_mktable, arm_crypto_mktable,
+ cpu_feature_p(CPUFEAT_ARM_PMULL));
+#endif
+#if CPUFAM_ARM64
+ DISPATCH_PICK_COND(gcm_mktable, arm64_pmull_mktable,
+ cpu_feature_p(CPUFEAT_ARM_PMULL));
+#endif
+ DISPATCH_PICK_FALLBACK(gcm_mktable, simple_mktable);
+}
+
+/* --- @recover_k@ --- *
+ *
+ * Arguments: @const gcm_params *p@ = pointer to the parameters
+ * @uint32 *k@ = block-sized vector in which to store %$k$%
+ * @const uint32 *ktab@ = the table encoding %$k$%
+ *
+ * Returns: ---
+ *
+ * Use: Recovers %$k$%, the secret from which @ktab@ was by
+ * @gcm_mktable@, from the table, and stores it in internal
+ * (big-endian) form in @k@.
+ */
+
+static void simple_recover_k(const gcm_params *p,
+ uint32 *k, const uint32 *ktab)
+{
+ unsigned i;
+
+ /* If the blockcipher is big-endian, then the key is simply in the first
+ * table element, in the right format. If the blockcipher is little-endian
+ * then it's in element 24, and the bytes need swapping.
+ */
+
+ if (!(p->f&GCMF_SWAP)) for (i = 0; i < p->n; i++) k[i] = ktab[i];
+ else for (i = 0; i < p->n; i++) k[i] = ENDSWAP32(ktab[24*p->n + i]);
+}
+
+#if CPUFAM_X86 || CPUFAM_AMD64
+static void pclmul_recover_k(const gcm_params *p,
+ uint32 *k, const uint32 *ktab)
+{
+ unsigned n = p->n;
+ unsigned nz;
+ const uint32 *t;
+
+ /* The representation is already independent of the blockcipher endianness.
+ * We need to compensate for padding, and reorder the words.
+ */
+
+ if (n == 3) nz = 1; else nz = 0;
+ t = ktab + n + nz;
+ while (n--) *k++ = *--t;
+}
+#endif
+
+#if CPUFAM_ARMEL
+static void arm_crypto_recover_k(const gcm_params *p,
+ uint32 *k, const uint32 *ktab)
+{
+ unsigned n = p->n;
+ const uint32 *t;
+
+ /* The representation is already independent of the blockcipher endianness.
+ * We only need to reorder the words.
+ */
+
+ t = ktab;
+ while (n >= 2) { k[1] = t[0]; k[0] = t[1]; t += 2; k += 2; n -= 2; }
+ if (n) k[0] = t[1];
+}
+#endif
+
+#if CPUFAM_ARM64
+static void arm64_pmull_recover_k(const gcm_params *p,
+ uint32 *k, const uint32 *ktab)
+{
+ unsigned n = p->n;
+ const uint32 *t;
+
+ /* The representation is already independent of the blockcipher endianness.
+ * We need to skip the duplicate pieces, and unscramble the bytes.
+ */
+
+ t = ktab;
+ while (n >= 2) {
+ k[0] = ENDSWAP32(rbit32(t[0]));
+ k[1] = ENDSWAP32(rbit32(t[1]));
+ t += 4; k += 2; n -= 2;
+ }
+ if (n) k[0] = ENDSWAP32(rbit32(t[0]));
+}
+#endif
+
+CPU_DISPATCH(static, EMPTY, void, recover_k,
+ (const gcm_params *p, uint32 *k, const uint32 *ktab),
+ (p, k, ktab),
+ pick_recover_k, simple_recover_k)
+
+static recover_k__functype *pick_recover_k(void)
+{
+#if CPUFAM_X86 || CPUFAM_AMD64
+ DISPATCH_PICK_COND(recover_k, pclmul_recover_k,
+ cpu_feature_p(CPUFEAT_X86_SSSE3) &&
+ cpu_feature_p(CPUFEAT_X86_PCLMUL));
+#endif
+#if CPUFAM_ARMEL
+ DISPATCH_PICK_COND(recover_k, arm_crypto_recover_k,
+ cpu_feature_p(CPUFEAT_ARM_PMULL));
+#endif
+#if CPUFAM_ARM64
+ DISPATCH_PICK_COND(recover_k, arm64_pmull_recover_k,
+ cpu_feature_p(CPUFEAT_ARM_PMULL));
+#endif
+ DISPATCH_PICK_FALLBACK(recover_k, simple_recover_k);
+}
+
+/* --- @gcm_mulk_N{b,l}@ --- *
+ *
+ * Arguments: @uint32 *a@ = accumulator to multiply
+ * @const uint32 *ktab@ = table constructed by @gcm_mktable@
+ *
+ * Returns: ---
+ *
+ * Use: Multiply @a@ by @k@ (implicitly represented in @ktab@),
+ * updating @a@ in-place. There are separate functions for each
+ * supported block size and endianness because this is the
+ * function whose performance actually matters.
+ */
+
+#if CPUFAM_X86 || CPUFAM_AMD64
+# define DECL_MULK_X86ISH(var) extern gcm_mulk_##var##__functype \
+ gcm_mulk_##var##_x86ish_pclmul_avx, \
+ gcm_mulk_##var##_x86ish_pclmul;
+# define PICK_MULK_X86ISH(var) do { \
+ DISPATCH_PICK_COND(gcm_mulk_##var, gcm_mulk_##var##_x86ish_pclmul_avx, \
+ cpu_feature_p(CPUFEAT_X86_AVX) && \
+ cpu_feature_p(CPUFEAT_X86_PCLMUL) && \
+ cpu_feature_p(CPUFEAT_X86_SSSE3)); \
+ DISPATCH_PICK_COND(gcm_mulk_##var, gcm_mulk_##var##_x86ish_pclmul, \
+ cpu_feature_p(CPUFEAT_X86_PCLMUL) && \
+ cpu_feature_p(CPUFEAT_X86_SSSE3)); \
+} while (0)
+#else
+# define DECL_MULK_X86ISH(var)
+# define PICK_MULK_X86ISH(var) do ; while (0)
+#endif
+
+#if CPUFAM_ARMEL
+# define DECL_MULK_ARM(var) \
+ extern gcm_mulk_##var##__functype gcm_mulk_##var##_arm_crypto;
+# define PICK_MULK_ARM(var) do { \
+ DISPATCH_PICK_COND(gcm_mulk_##var, gcm_mulk_##var##_arm_crypto, \
+ cpu_feature_p(CPUFEAT_ARM_PMULL)); \
+} while (0)
+#else
+# define DECL_MULK_ARM(var)
+# define PICK_MULK_ARM(var) do ; while (0)
+#endif
+
+#if CPUFAM_ARM64
+# define DECL_MULK_ARM64(var) \
+ extern gcm_mulk_##var##__functype gcm_mulk_##var##_arm64_pmull;
+# define PICK_MULK_ARM64(var) do { \
+ DISPATCH_PICK_COND(gcm_mulk_##var, gcm_mulk_##var##_arm64_pmull, \
+ cpu_feature_p(CPUFEAT_ARM_PMULL)); \
+} while (0)
+#else
+# define DECL_MULK_ARM64(var)
+# define PICK_MULK_ARM64(var) do ; while (0)
+#endif
+
+#define DEF_MULK(nbits) \
+ \
+CPU_DISPATCH(EMPTY, EMPTY, void, gcm_mulk_##nbits##b, \
+ (uint32 *a, const uint32 *ktab), (a, ktab), \
+ pick_mulk_##nbits##b, simple_mulk_##nbits) \
+CPU_DISPATCH(EMPTY, EMPTY, void, gcm_mulk_##nbits##l, \
+ (uint32 *a, const uint32 *ktab), (a, ktab), \
+ pick_mulk_##nbits##l, simple_mulk_##nbits) \
+ \
+static void simple_mulk_##nbits(uint32 *a, const uint32 *ktab) \
+{ \
+ uint32 m, t; \
+ uint32 z[nbits/32]; \
+ unsigned i, j, k; \
+ \
+ for (i = 0; i < nbits/32; i++) z[i] = 0; \
+ \
+ for (i = 0; i < nbits/32; i++) { \
+ t = a[i]; \
+ for (j = 0; j < 32; j++) { \
+ m = -((t >> 31)&1u); \
+ for (k = 0; k < nbits/32; k++) z[k] ^= *ktab++&m; \
+ t <<= 1; \
+ } \
+ } \
+ \
+ for (i = 0; i < nbits/32; i++) a[i] = z[i]; \
+} \
+ \
+DECL_MULK_X86ISH(nbits##b) \
+DECL_MULK_ARM(nbits##b) \
+DECL_MULK_ARM64(nbits##b) \
+static gcm_mulk_##nbits##b##__functype *pick_mulk_##nbits##b(void) \
+{ \
+ PICK_MULK_X86ISH(nbits##b); \
+ PICK_MULK_ARM(nbits##b); \
+ PICK_MULK_ARM64(nbits##b); \
+ DISPATCH_PICK_FALLBACK(gcm_mulk_##nbits##b, simple_mulk_##nbits); \
+} \
+ \
+DECL_MULK_X86ISH(nbits##l) \
+DECL_MULK_ARM(nbits##l) \
+DECL_MULK_ARM64(nbits##l) \
+static gcm_mulk_##nbits##l##__functype *pick_mulk_##nbits##l(void) \
+{ \
+ PICK_MULK_X86ISH(nbits##l); \
+ PICK_MULK_ARM(nbits##l); \
+ PICK_MULK_ARM64(nbits##l); \
+ DISPATCH_PICK_FALLBACK(gcm_mulk_##nbits##l, simple_mulk_##nbits); \
+}
+
+GCM_WIDTHS(DEF_MULK)
+
+#define GCM_MULK_CASE(nbits) \
+ case nbits/32: \
+ if (_f&GCMF_SWAP) gcm_mulk_##nbits##l(_a, _ktab); \
+ else gcm_mulk_##nbits##b(_a, _ktab); \
+ break;
+#define MULK(n, f, a, ktab) do { \
+ uint32 *_a = (a); const uint32 *_ktab = (ktab); \
+ unsigned _f = (f); \
+ switch (n) { \
+ GCM_WIDTHS(GCM_MULK_CASE) \
+ default: abort(); \
+ } \
+} while (0)
+
+/*----- Other utilities ---------------------------------------------------*/
+
+/* --- @putlen@ --- *
+ *
+ * Arguments: @octet *p@ = pointer to output buffer
+ * @unsigned w@ = size of output buffer
+ * @unsigned blksz@ = block size (assumed fairly small)
+ * @unsigned long nblocks@ = number of blocks
+ * @unsigned nbytes@ = tail size in bytes (assumed small)
+ *
+ * Returns: ---
+ *
+ * Use: Store the overall length in %$\emph{bits}$% (i.e.,
+ * @3*(nblocks*blksz + nbytes)@ in big-endian form in the
+ * buffer @p@.
+ */
+
+static void putlen(octet *p, unsigned w, unsigned blksz,
+ unsigned long nblocks, unsigned nbytes)
+{
+ unsigned long nblo = nblocks&((1ul << (ULONG_BITS/2)) - 1),
+ nbhi = nblocks >> ULONG_BITS/2;
+ unsigned long nlo = nblo*blksz + nbytes, nhi = nbhi*blksz;
+
+ /* This is fiddly. Split @nblocks@, which is the big number, into high and
+ * low halves, multiply those separately by @blksz@, propagate carries, and
+ * then multiply by eight.
+ */
+ nhi += nlo >> ULONG_BITS/2;
+ nlo &= (1ul << (ULONG_BITS/2)) - 1;
+ nlo <<= 3;
+
+ /* Now write out the size, feeding bits in from @nhi@ as necessary. */
+ p += w;
+ while (w--) {
+ *--p = U8(nlo);
+ nlo = (nlo >> 8) | ((nhi&0xff) << (ULONG_BITS/2 - 5));
+ nhi >>= 8;
+ }
+}
+
+/* --- @mix@ --- *
+ *
+ * Arguments: @const gcm_params *p@ = pointer to the parameters
+ * @uint32 *a@ = GHASH accumulator
+ * @const octet *q@ = pointer to an input block
+ * @const uint32 *ktab@ = multiplication table, built by
+ * @gcm_mktable@
+ *
+ * Returns: ---
+ *
+ * Use: Fold the block @q@ into the GHASH accumulator. The
+ * calculation is %$a' = k (a + q)$%.
+ */
+
+static void mix(const gcm_params *p, uint32 *a,
+ const octet *q, const uint32 *ktab)
+{
+ unsigned i;
+
+ if (p->f&GCMF_SWAP)
+ for (i = 0; i < p->n; i++) { a[i] ^= LOAD32_L(q); q += 4; }
+ else
+ for (i = 0; i < p->n; i++) { a[i] ^= LOAD32_B(q); q += 4; }
+ MULK(p->n, p->f, a, ktab);
+}
+
+/* --- @gcm_ghashdone@ --- *
+ *
+ * Arguments: @const gcm_params *p@ = pointer to the parameters
+ * @uint32 *a@ = GHASH accumulator
+ * @const uint32 *ktab@ = multiplication table, built by
+ * @gcm_mktable@
+ * @unsigned long xblocks, yblocks@ = number of whole blocks in
+ * the two inputs
+ * @unsigned xbytes, ybytes@ = number of trailing bytes in the
+ * two inputs
+ *
+ * Returns: ---
+ *
+ * Use: Finishes a GHASH operation by appending the appropriately
+ * encoded lengths of the two constituent messages.
+ */
+
+void gcm_ghashdone(const gcm_params *p, uint32 *a, const uint32 *ktab,
+ unsigned long xblocks, unsigned xbytes,
+ unsigned long yblocks, unsigned ybytes)
+{
+ octet b[4*GCM_NMAX];
+ unsigned w = p->n < 3 ? 4*p->n : 2*p->n;
+
+ /* Construct the encoded lengths. Note that smaller-block versions of GCM
+ * encode the lengths in separate blocks. GCM is only officially defined
+ * for 64- and 128-bit blocks; I've placed the cutoff somewhat arbitrarily
+ * at 96 bits.
+ */
+ putlen(b, w, 4*p->n, xblocks, xbytes);
+ putlen(b + w, w, 4*p->n, yblocks, ybytes);
+
+ /* Feed the lengths into the accumulator. */
+ mix(p, a, b, ktab);
+ if (p->n < 3) mix(p, a, b + w, ktab);
+}
+
+/* --- @gcm_concat@ --- *
+ *
+ * Arguments: @const gcm_params *p@ = pointer to the parameters
+ * @uint32 *z@ = GHASH accumulator for suffix, updated
+ * @const uint32 *x@ = GHASH accumulator for prefix
+ * @const uint32 *ktab@ = multiplication table, built by
+ * @gcm_mktable@
+ * @unsigned long n@ = length of suffix in whole blocks
+ *
+ * Returns: ---
+ *
+ * Use: On entry, @x@ and @z@ are the results of hashing two strings
+ * %$a$% and %$b$%, each a whole number of blocks long; in
+ * particular, %$b$% is @n@ blocks long. On exit, @z@ is
+ * updated to be the hash of %$a \cat b$%.
+ */
+
+void gcm_concat(const gcm_params *p, uint32 *z, const uint32 *x,
+ const uint32 *ktab, unsigned long n)
+{
+ uint32 t[GCM_NMAX], u[GCM_NMAX];
+ unsigned i, j;
+
+ if (!n) {
+ /* If @n@ is zero, then there's not much to do. The mathematics
+ * (explained below) still works, but the code takes a shortcut which
+ * doesn't handle this case: so set %$z' = z + x k^n = z + x$%.
+ */
+
+ for (j = 0; j < p->n; j++) z[j] ^= x[j];
+ } else {
+ /* We have %$x = a_0 t^m + \cdots + a_{m-2} t^2 + a_{m-1} t$% and
+ * %$z = b_0 t^n + \cdots + b_{n-2} t^2 + b_{n-1} t$%. What we'd like is
+ * the hash of %$a \cat b$%, which is %$z + x k^n$%.
+ *
+ * The first job, then, is to calculate %$k^n$%, and for this we use a
+ * simple left-to-right square-and-multiply algorithm. There's no need
+ * to keep %$n$% secret here.
+ */
+
+ /* Start by retrieving %$k$% from the table, and convert it to big-endian
+ * form.
+ */
+ recover_k(p, u, ktab);
+
+ /* Now calculate %$k^n$%. */
+ i = ULONG_BITS;
+#define BIT (1ul << (ULONG_BITS - 1))
+ while (!(n&BIT)) { n <<= 1; i--; }
+ n <<= 1; i--; for (j = 0; j < p->n; j++) t[j] = u[j];
+ while (i--) { mul(p, t, t, t); if (n&BIT) mul(p, t, t, u); n <<= 1; }
+#undef BIT
+
+ /* Next, calculate %$x k^n$%. If we're using a little-endian convention
+ * then we must convert %$x$%; otherwise we can just use it in place.
+ */
+ if (!(p->f&GCMF_SWAP))
+ mul(p, t, t, x);
+ else {
+ for (j = 0; j < p->n; j++) u[j] = ENDSWAP32(x[j]);
+ mul(p, t, t, u);
+ }
+
+ /* Finally, add %$x k^n$% onto %$z$%, converting back to little-endian if
+ * necessary.
+ */
+ if (!(p->f&GCMF_SWAP)) for (j = 0; j < p->n; j++) z[j] ^= t[j];
+ else for (j = 0; j < p->n; j++) z[j] ^= ENDSWAP32(t[j]);
+ }
+}
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <mLib/quis.h>
+#include <mLib/testrig.h>
+
+static void report_failure(const char *test, unsigned nbits,
+ const char *ref, dstr v[], dstr *d)
+{
+ printf("test %s failed (nbits = %u)", test, nbits);
+ printf("\n\tx = "); type_hex.dump(&v[0], stdout);
+ printf("\n\ty = "); type_hex.dump(&v[1], stdout);
+ printf("\n\tz = "); type_hex.dump(&v[2], stdout);
+ printf("\n\t%s' = ", ref); type_hex.dump(d, stdout);
+ putchar('\n');
+}
+
+static void mulk(unsigned nbits, unsigned f, uint32 *x, const uint32 *ktab)
+ { MULK(nbits/32, f, x, ktab); }
+
+static int test_mul(uint32 poly, dstr v[])
+{
+ uint32 x[GCM_NMAX], y[GCM_NMAX], z[GCM_NMAX], ktab[32*GCM_NMAX*GCM_NMAX];
+ gcm_params p;
+ dstr d = DSTR_INIT;
+ unsigned i, nbits;
+ int ok = 1;
+ enum { I_x, I_y, I_z };
+
+ nbits = 8*v[0].len; p.f = 0; p.n = nbits/32; p.poly = poly;
+ dstr_ensure(&d, nbits/8); d.len = nbits/8;
+
+#define LOADXY(E) do { \
+ for (i = 0; i < nbits/32; i++) { \
+ x[i] = LOAD32_##E(v[I_x].buf + 4*i); \
+ y[i] = LOAD32_##E(v[I_y].buf + 4*i); \
+ } \
+} while (0)
+
+#define INITZ(x) do { \
+ for (i = 0; i < nbits/32; i++) z[i] = (x)[i]; \
+} while (0)
+
+#define CHECK(E, what, ref) do { \
+ for (i = 0; i < nbits/32; i++) STORE32_##E(d.buf + 4*i, z[i]); \
+ if (memcmp(d.buf, v[I_##ref].buf, nbits/8) != 0) \
+ { ok = 0; report_failure(what, nbits, #ref, v, &d); } \
+} while (0)
+
+#define TEST_PREP_1(E, x, y, what) do { \
+ gcm_mktable(&p, ktab, y); \
+ recover_k(&p, z, ktab); CHECK(B, "mktable/recover_k (" #y ")", y); \
+ INITZ(x); mulk(nbits, p.f, z, ktab); CHECK(E, what " (k = " #y ")", z); \
+} while (0)
+
+#define TEST_PREP(E, what) do { \
+ TEST_PREP_1(E, x, y, what); \
+ TEST_PREP_1(E, y, x, what); \
+} while (0)
+
+ /* First, test plain multiply. */
+ LOADXY(B); mul(&p, z, x, y); CHECK(B, "gcm_mul", z);
+
+ /* Next, test big-endian prepared key. */
+ LOADXY(B); TEST_PREP(B, "gcm_kmul_b");
+
+ /* Finally, test little-endian prepared key. */
+ p.f = GCMF_SWAP; LOADXY(L);
+ TEST_PREP(L, "gcm_kmul_l");
+
+#undef LOADXY
+#undef INITZ
+#undef CHECK
+#undef TEST_PREP_1
+#undef TEST_PREP
+
+ /* All done. */
+ return (ok);
+}
+
+#define TEST(nbits) \
+static int test_mul_##nbits(dstr v[]) \
+ { return (test_mul(GCM_POLY_##nbits, v)); }
+GCM_WIDTHS(TEST)
+#undef TEST
+
+static test_chunk defs[] = {
+#define TEST(nbits) \
+ { "gcm-mul" #nbits, test_mul_##nbits, \
+ { &type_hex, &type_hex, &type_hex, 0 } },
+GCM_WIDTHS(TEST)
+#undef TEST
+ { 0, 0, { 0 } }
+};
+
+int main(int argc, char *argv[])
+{
+ ego(argv[0]);
+ test_run(argc, argv, defs, SRCDIR"/t/gcm");
+ return (0);
+}
+
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
--- /dev/null
+/* -*-c-*-
+ *
+ * The GCM authenticated encryption mode
+ *
+ * (c) 2018 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*----- Notes on GCM ------------------------------------------------------*
+ *
+ * The name is short for `Galois Counter Mode'. GCM was designed in 2005 by
+ * David McGrew and John Viega as a fast, patent-free authenticated
+ * encryption scheme; and it's specified by NIST in SP800-38D. It combines
+ * counter-mode encryption with a Carter--Wegman authenticator based on a
+ * polynomial hash over %$\gf{2^{128}}%, so it needs only one blockcipher
+ * application per message block, together with a multiplication by a
+ * constant in the finite field. GCM is essentially the winner in the
+ * authenticated-encryption-mode competition, to the extent that Intel and
+ * ARM both added instructions to their architectures to accelerate it.
+ *
+ * GCM allows arbitrary-sized nonces, though it's happiest if the nonce is 32
+ * bits shorter than the block size, leaving a fixed-size block counter in
+ * the low 32 bits. It permits header data to be processed independently of
+ * the message, though doing this requires some slightly fiddly algebra and
+ * most implementations don't allow callers to take advantage of this.
+ *
+ * One downside is that the field multiplication is inefficient in software.
+ * Back in 2005 it was assumed that implementors would use large tables, but
+ * that leaks the authentication secret through the processor cache. This
+ * implementation runs in constant time, but the penalty is that, without
+ * dedicated processor support, it's much slower than an extra blockcipher
+ * application would have been.
+ *
+ * Another downside is that, while GCM came with a security proof, it was
+ * subtly incorrect in a few ways which mean that its concrete security is
+ * significantly less than one would expect.
+ *
+ * If interoperability isn't a concern, then OCB3 is probably a better
+ * choice; if the OCB patent situation is also worrying, then EAX is likely
+ * preferable.
+ */
+
+#ifndef CATACOMB_GCM_H
+#define CATACOMB_GCM_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+#include <mLib/buf.h>
+
+#ifndef CATACOMB_GAEAD_H
+# include "gaead.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @GCM_DECL@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Creates declarations for GCM authenticated-encryption mode.
+ */
+
+#define GCM_DECL(PRE, pre) \
+ \
+typedef struct pre##_gcmkey { \
+ pre##_ctx ctx; /* Block cipher key */ \
+ uint32 ktab[32*PRE##_BLKSZ*PRE##_BLKSZ]; /* Multiplication table */ \
+} pre##_gcmkey; \
+ \
+typedef struct pre##_gcmaadctx { \
+ pre##_gcmkey k; /* Underlying key */ \
+ uint32 a[PRE##_BLKSZ/4]; /* GHASH accumulator */ \
+ octet b[PRE##_BLKSZ]; /* Input buffer */ \
+ unsigned off; /* Length of stuff in buffer */ \
+ unsigned long len; /* Number of blocks so far */ \
+} pre##_gcmaadctx; \
+ \
+typedef struct pre##_gcmctx { \
+ /* The buffer is split into two portions. The first N octets hold a \
+ * chunk of ciphertext, which will be fed into the OMAC calculation; \
+ * the remaining BLKSZ - N octets hold E_K(C), which is the XOR mask \
+ * to apply to the plaintext or ciphertext. \
+ */ \
+ pre##_gcmkey k; /* Underlying key */ \
+ uint32 c[PRE##_BLKSZ/4]; /* Current counter value */ \
+ uint32 c0[PRE##_BLKSZ/4]; /* Initial counter */ \
+ uint32 a[PRE##_BLKSZ]; /* GHASH accumulator */ \
+ octet b[PRE##_BLKSZ]; /* Ciphertext/mask buffer */ \
+ unsigned off; /* Crossover point in buffer */ \
+ unsigned long len; /* Number of blocks so far */ \
+} pre##_gcmctx; \
+ \
+extern const octet pre##_gcmnoncesz[], pre##_gcmtagsz[]; \
+ \
+/* --- @pre_gcmsetkey@ --- * \
+ * \
+ * Arguments: @pre_gcmkey *key@ = pointer to key block to fill in \
+ * @const void *k@ = pointer to key material \
+ * @size_t ksz@ = size of key material \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes an GCM key block. \
+ */ \
+ \
+extern void pre##_gcmsetkey(pre##_gcmkey */*key*/, \
+ const void */*k*/, size_t /*ksz*/); \
+ \
+/* --- @pre_gcmaadinit@ --- * \
+ * \
+ * Arguments: @pre_gcmaadctx *aad@ = pointer to AAD context \
+ * @const pre_gcmkey *key@ = pointer to key block \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes an GCM AAD (`additional authenticated \
+ * data') context associated with a given key. AAD \
+ * contexts can be copied and/or reused, saving time if \
+ * the AAD for a number of messages has a common prefix. \
+ * \
+ * The @key@ doesn't need to be kept around, though \
+ * usually there'll at least be another copy in some GCM \
+ * operation context because the AAD on its own isn't much \
+ * good. \
+ */ \
+ \
+extern void pre##_gcmaadinit(pre##_gcmaadctx */*aad*/, \
+ const pre##_gcmkey */*key*/); \
+ \
+/* --- @pre_gcmaadhash@ --- * \
+ * \
+ * Arguments: @pre_gcmaadctx *aad@ = pointer to AAD context \
+ * @const void *p@ = pointer to AAD material \
+ * @size_t sz@ = length of AAD material \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Feeds AAD into the context. \
+ */ \
+ \
+extern void pre##_gcmaadhash(pre##_gcmaadctx */*aad*/, \
+ const void */*p*/, size_t /*sz*/); \
+ \
+/* --- @pre_gcminit@ --- * \
+ * \
+ * Arguments: @pre_gcmctx *ctx@ = pointer to GCM context \
+ * @const pre_gcmkey *key@ = pointer to key block \
+ * @const void *n@ = pointer to nonce \
+ * @size_t nsz@ = size of nonce \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initialize an GCM operation context with a given key. \
+ * \
+ * The original key needn't be kept around any more. \
+ */ \
+ \
+extern void pre##_gcminit(pre##_gcmctx */*ctx*/, \
+ const pre##_gcmkey */*k*/, \
+ const void */*n*/, size_t /*nsz*/); \
+ \
+/* --- @pre_gcmreinit@ --- * \
+ * \
+ * Arguments: @pre_gcmctx *ctx@ = pointer to GCM context \
+ * @const void *n@ = pointer to nonce \
+ * @size_t nsz@ = size of nonce \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Reinitialize an GCM operation context, changing the \
+ * nonce. \
+ */ \
+ \
+extern void pre##_gcmreinit(pre##_gcmctx */*ctx*/, \
+ const void */*n*/, size_t /*nsz*/); \
+ \
+/* --- @pre_gcmencrypt@ --- * \
+ * \
+ * Arguments: @pre_gcmctx *ctx@ = pointer to GCM operation context \
+ * @const void *src@ = pointer to plaintext message chunk \
+ * @size_t sz@ = size of the plaintext \
+ * @buf *dst@ = a buffer to write the ciphertext to \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Encrypts a chunk of a plaintext message, writing a \
+ * chunk of ciphertext to the output buffer and updating \
+ * the operation state. \
+ * \
+ * For GCM, we always write a ciphertext chunk the same \
+ * size as the plaintext. The messing about with @buf@ \
+ * objects makes the interface consistent with other AEAD \
+ * schemes which can't do this. \
+ */ \
+ \
+extern int pre##_gcmencrypt(pre##_gcmctx */*ctx*/, \
+ const void */*src*/, size_t /*sz*/, \
+ buf */*dst*/); \
+ \
+/* --- @pre_gcmdecrypt@ --- * \
+ * \
+ * Arguments: @pre_gcmctx *ctx@ = pointer to GCM operation context \
+ * @const void *src@ = pointer to ciphertext message chunk \
+ * @size_t sz@ = size of the ciphertext \
+ * @buf *dst@ = a buffer to write the plaintext to \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Decrypts a chunk of a ciphertext message, writing a \
+ * chunk of plaintext to the output buffer and updating \
+ * the operation state. \
+ * \
+ * For GCM, we always write a plaintext chunk the same \
+ * size as the ciphertext. The messing about with @buf@ \
+ * objects makes the interface consistent with other AEAD \
+ * schemes which can't do this. \
+ */ \
+ \
+extern int pre##_gcmdecrypt(pre##_gcmctx */*ctx*/, \
+ const void */*src*/, size_t /*sz*/, \
+ buf */*dst*/); \
+ \
+/* --- @pre_gcmencryptdone@ --- * \
+ * \
+ * Arguments: @pre_gcmctx *ctx@ = pointer to an GCM context \
+ * @const pre_gcmaadctx *aad@ = pointer to AAD context, or \
+ * null \
+ * @buf *dst@ = buffer for remaining ciphertext \
+ * @void *tag@ = where to write the tag \
+ * @size_t tsz@ = length of tag to store \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Completes an GCM encryption operation. The @aad@ \
+ * pointer may be null if there is no additional \
+ * authenticated data. GCM doesn't buffer ciphertext, but \
+ * the output buffer is provided anyway for consistency \
+ * with other AEAD schemes which don't have this property; \
+ * the function will fail if the output buffer is broken. \
+ */ \
+ \
+extern int pre##_gcmencryptdone(pre##_gcmctx */*ctx*/, \
+ const pre##_gcmaadctx */*aad*/, \
+ buf */*dst*/, \
+ void */*tag*/, size_t /*tsz*/); \
+ \
+/* --- @pre_gcmdecryptdone@ --- * \
+ * \
+ * Arguments: @pre_gcmctx *ctx@ = pointer to an GCM context \
+ * @const pre_gcmaadctx *aad@ = pointer to AAD context, or \
+ * null \
+ * @buf *dst@ = buffer for remaining plaintext \
+ * @const void *tag@ = tag to verify \
+ * @size_t tsz@ = length of tag \
+ * \
+ * Returns: @+1@ for complete success; @0@ if tag verification \
+ * failed; @-1@ for other kinds of errors. \
+ * \
+ * Use: Completes an GCM decryption operation. The @aad@ \
+ * pointer may be null if there is no additional \
+ * authenticated data. GCM doesn't buffer plaintext, but \
+ * the output buffer is provided anyway for consistency \
+ * with other AEAD schemes which don't have this property; \
+ * the function will fail if the output buffer is broken. \
+ */ \
+ \
+extern int pre##_gcmdecryptdone(pre##_gcmctx */*ctx*/, \
+ const pre##_gcmaadctx */*aad*/, \
+ buf */*dst*/, \
+ const void */*tag*/, size_t /*tsz*/); \
+ \
+/* --- Generic AEAD interface --- */ \
+ \
+extern const gcaead pre##_gcm;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
#include <mLib/bits.h>
+#ifndef CATACOMB_RSVR_H
+# include "rsvr.h"
+#endif
+
/*----- Macros ------------------------------------------------------------*/
/* --- @HASH_BUFFER@ --- *
#define HASH_BUFFER(PRE, pre, ictx, ibuf, isz) do { \
pre##_ctx *_bctx = (ictx); \
size_t _bsz = (isz); \
- const octet *_bbuf = (octet *)(ibuf); \
+ const octet *_bbuf = (octet *)(ibuf), *_p; \
+ static const rsvr_policy _pol = { 0, PRE##_BUFSZ, PRE##_BUFSZ }; \
+ uint32 _l, _h; \
+ rsvr_state _st; \
\
/* --- Add on the size done so far --- * \
* \
* how many bits you've actually got. \
*/ \
\
- { \
- uint32 _l = U32(_bsz); \
- uint32 _h = ((_bsz & ~(size_t)MASK32) >> 16) >> 16; \
- _bctx->nh += _h; \
- _bctx->nl += _l; \
- if (_bctx->nl < _l || _bctx->nl & ~(uint32)MASK32) \
- _bctx->nh++; \
- } \
- \
- /* --- Handle very small contributions --- */ \
- \
- if (_bctx->off + _bsz < PRE##_BUFSZ) { \
- memcpy(_bctx->buf + _bctx->off, _bbuf, _bsz); \
- _bctx->off += _bsz; \
- } else { \
- \
- /* --- Handle an initial partial buffer --- */ \
+ _l = U32(_bsz); _h = ((_bsz & ~(size_t)MASK32) >> 16) >> 16; \
+ _bctx->nl += _l; if (_bctx->nl < _l || _bctx->nl & ~(uint32)MASK32) _h++; \
+ _bctx->nh += _h; \
\
- if (_bctx->off) { \
- size_t s = PRE##_BUFSZ - _bctx->off; \
- memcpy(_bctx->buf + _bctx->off, _bbuf, s); \
- pre##_compress(_bctx, _bctx->buf); \
- _bsz -= s; _bbuf += s; \
- } \
- \
- /* --- Do whole buffers while we can --- */ \
- \
- while (_bsz >= PRE##_BUFSZ) { \
- pre##_compress(_bctx, _bbuf); \
- _bsz -= PRE##_BUFSZ; _bbuf += PRE##_BUFSZ; \
- } \
- \
- /* --- And wrap up at the end --- */ \
+ /* --- Accumulate the input data --- */ \
\
- if (_bsz) \
- memcpy(_bctx->buf, _bbuf, _bsz); \
- _bctx->off = _bsz; \
- } \
+ rsvr_setup(&_st, &_pol, _bctx->buf, &_bctx->off, _bbuf, _bsz); \
+ RSVR_DO(&_st) while ((_p = RSVR_NEXT(&_st, PRE##_BUFSZ)) != 0) \
+ pre##_compress(_bctx, _p); \
} while (0)
/* --- @HASH_PAD@ --- *
*/ \
\
void pre##_machash(pre##_macctx *ctx, const void *buf, size_t sz) \
-{ \
- pre##_hash(&ctx->ctx, buf, sz); \
-} \
+ { pre##_hash(&ctx->ctx, buf, sz); } \
\
/* --- @pre_macdone@ --- * \
* \
* result to Z.
*/
- lane b[5], c[5], d[5], t;
+ lane c[5], d[5], t;
/* Theta, first step: calculate the column parities. */
#define COLPARITY(j) do { \
- c[j] = x->S[I(j, 0)]; \
- XOR_LANE(c[j], c[j], x->S[I(j, 1)]); \
- XOR_LANE(c[j], c[j], x->S[I(j, 2)]); \
- XOR_LANE(c[j], c[j], x->S[I(j, 3)]); \
- XOR_LANE(c[j], c[j], x->S[I(j, 4)]); \
+ d[j] = x->S[I(j, 0)]; \
+ XOR_LANE(d[j], d[j], x->S[I(j, 1)]); \
+ XOR_LANE(d[j], d[j], x->S[I(j, 2)]); \
+ XOR_LANE(d[j], d[j], x->S[I(j, 3)]); \
+ XOR_LANE(d[j], d[j], x->S[I(j, 4)]); \
} while (0)
COLPARITY(0); COLPARITY(1); COLPARITY(2); COLPARITY(3); COLPARITY(4);
#undef COLPARITY
/* Theta, second step: calculate the combined effect. */
- ROTL_LANE(d[0], c[1], 1); XOR_LANE(d[0], d[0], c[4]);
- ROTL_LANE(d[1], c[2], 1); XOR_LANE(d[1], d[1], c[0]);
- ROTL_LANE(d[2], c[3], 1); XOR_LANE(d[2], d[2], c[1]);
- ROTL_LANE(d[3], c[4], 1); XOR_LANE(d[3], d[3], c[2]);
- ROTL_LANE(d[4], c[0], 1); XOR_LANE(d[4], d[4], c[3]);
+ ROTL_LANE(c[0], d[1], 1); XOR_LANE(c[0], c[0], d[4]);
+ ROTL_LANE(c[1], d[2], 1); XOR_LANE(c[1], c[1], d[0]);
+ ROTL_LANE(c[2], d[3], 1); XOR_LANE(c[2], c[2], d[1]);
+ ROTL_LANE(c[3], d[4], 1); XOR_LANE(c[3], c[3], d[2]);
+ ROTL_LANE(c[4], d[0], 1); XOR_LANE(c[4], c[4], d[3]);
/* Now we work plane by plane through the output. To do this, we must undo
* the pi transposition. Pi maps (x', y') = (y, 2 x + 3 y), so y = x', and
#define THETA_RHO(i0, i1, i2, i3, i4) do { \
\
/* First, theta. */ \
- XOR_LANE(b[0], x->S[I(i0, 0)], d[i0]); \
- XOR_LANE(b[1], x->S[I(i1, 1)], d[i1]); \
- XOR_LANE(b[2], x->S[I(i2, 2)], d[i2]); \
- XOR_LANE(b[3], x->S[I(i3, 3)], d[i3]); \
- XOR_LANE(b[4], x->S[I(i4, 4)], d[i4]); \
+ XOR_LANE(d[0], x->S[I(i0, 0)], c[i0]); \
+ XOR_LANE(d[1], x->S[I(i1, 1)], c[i1]); \
+ XOR_LANE(d[2], x->S[I(i2, 2)], c[i2]); \
+ XOR_LANE(d[3], x->S[I(i3, 3)], c[i3]); \
+ XOR_LANE(d[4], x->S[I(i4, 4)], c[i4]); \
\
/* Then rho. */ \
- ROTL_LANE(b[0], b[0], ROT_##i0##_0); \
- ROTL_LANE(b[1], b[1], ROT_##i1##_1); \
- ROTL_LANE(b[2], b[2], ROT_##i2##_2); \
- ROTL_LANE(b[3], b[3], ROT_##i3##_3); \
- ROTL_LANE(b[4], b[4], ROT_##i4##_4); \
+ ROTL_LANE(d[0], d[0], ROT_##i0##_0); \
+ ROTL_LANE(d[1], d[1], ROT_##i1##_1); \
+ ROTL_LANE(d[2], d[2], ROT_##i2##_2); \
+ ROTL_LANE(d[3], d[3], ROT_##i3##_3); \
+ ROTL_LANE(d[4], d[4], ROT_##i4##_4); \
} while (0)
/* The basic chi operation is: z = w ^ (~a&b), but this involves an
* This is hairy because we must worry about complementation.
*/
THETA_RHO(0, 1, 2, 3, 4);
- CHI_COMPL(t, b[2]); /* [.] */
- CHI_101_0(z->S[I(0, 0)], b[0], b[1], b[2]); /* * . * -> . */
- CHI_001_1(z->S[I(1, 0)], b[1], t, b[3]); /* . [.] * -> * */
- CHI_110_1(z->S[I(2, 0)], b[2], b[3], b[4]); /* * * . -> * */
- CHI_101_0(z->S[I(3, 0)], b[3], b[4], b[0]); /* * * . -> . */
- CHI_010_0(z->S[I(4, 0)], b[4], b[0], b[1]); /* * . . -> . */
+ CHI_COMPL(t, d[2]); /* [.] */
+ CHI_101_0(z->S[I(0, 0)], d[0], d[1], d[2]); /* * . * -> . */
+ CHI_001_1(z->S[I(1, 0)], d[1], t, d[3]); /* . [.] * -> * */
+ CHI_110_1(z->S[I(2, 0)], d[2], d[3], d[4]); /* * * . -> * */
+ CHI_101_0(z->S[I(3, 0)], d[3], d[4], d[0]); /* * * . -> . */
+ CHI_010_0(z->S[I(4, 0)], d[4], d[0], d[1]); /* * . . -> . */
/* We'd better do iota before we forget. */
XOR_LANE(z->S[I(0, 0)], z->S[I(0, 0)], rcon[i]);
/* That was fun. Maybe y' = 1 will be as good. */
THETA_RHO(3, 4, 0, 1, 2);
- CHI_COMPL(t, b[4]); /* [*] */
- CHI_101_0(z->S[I(0, 1)], b[0], b[1], b[2]); /* * . * -> . */
- CHI_010_0(z->S[I(1, 1)], b[1], b[2], b[3]); /* . * . -> . */
- CHI_101_0(z->S[I(2, 1)], b[2], b[3], t); /* * . [*] -> . */
- CHI_001_1(z->S[I(3, 1)], b[3], b[4], b[0]); /* * . . -> * */
- CHI_010_0(z->S[I(4, 1)], b[4], b[0], b[1]); /* * . . -> . */
+ CHI_COMPL(t, d[4]); /* [*] */
+ CHI_101_0(z->S[I(0, 1)], d[0], d[1], d[2]); /* * . * -> . */
+ CHI_010_0(z->S[I(1, 1)], d[1], d[2], d[3]); /* . * . -> . */
+ CHI_101_0(z->S[I(2, 1)], d[2], d[3], t); /* * . [*] -> . */
+ CHI_001_1(z->S[I(3, 1)], d[3], d[4], d[0]); /* * . . -> * */
+ CHI_010_0(z->S[I(4, 1)], d[4], d[0], d[1]); /* * . . -> . */
/* We're getting the hang of this. The y' = 2 plane shouldn't be any
* trouble.
*/
THETA_RHO(1, 2, 3, 4, 0);
- CHI_COMPL(t, b[3]); /* [*] */
- CHI_101_0(z->S[I(0, 2)], b[0], b[1], b[2]); /* * . * -> . */
- CHI_010_0(z->S[I(1, 2)], b[1], b[2], b[3]); /* . * . -> . */
- CHI_110_1(z->S[I(2, 2)], b[2], t, b[4]); /* * [*] . -> * */
- CHI_101_0(z->S[I(3, 2)], t, b[4], b[0]); /* * [*] . -> . */
- CHI_010_0(z->S[I(4, 2)], b[4], b[0], b[1]); /* * . . -> . */
+ CHI_COMPL(t, d[3]); /* [*] */
+ CHI_101_0(z->S[I(0, 2)], d[0], d[1], d[2]); /* * . * -> . */
+ CHI_010_0(z->S[I(1, 2)], d[1], d[2], d[3]); /* . * . -> . */
+ CHI_110_1(z->S[I(2, 2)], d[2], t, d[4]); /* * [*] . -> * */
+ CHI_101_0(z->S[I(3, 2)], t, d[4], d[0]); /* * [*] . -> . */
+ CHI_010_0(z->S[I(4, 2)], d[4], d[0], d[1]); /* * . . -> . */
/* This isn't as interesting any more. Let's do y' = 3 before boredom sets
* in.
*/
THETA_RHO(4, 0, 1, 2, 3);
- CHI_COMPL(t, b[3]); /* [.] */
- CHI_010_0(z->S[I(0, 3)], b[0], b[1], b[2]); /* . * . -> . */
- CHI_101_0(z->S[I(1, 3)], b[1], b[2], b[3]); /* * . * -> . */
- CHI_001_1(z->S[I(2, 3)], b[2], t, b[4]); /* . [.] * -> * */
- CHI_010_0(z->S[I(3, 3)], t, b[4], b[0]); /* . [.] * -> . */
- CHI_101_0(z->S[I(4, 3)], b[4], b[0], b[1]); /* . * * -> . */
+ CHI_COMPL(t, d[3]); /* [.] */
+ CHI_010_0(z->S[I(0, 3)], d[0], d[1], d[2]); /* . * . -> . */
+ CHI_101_0(z->S[I(1, 3)], d[1], d[2], d[3]); /* * . * -> . */
+ CHI_001_1(z->S[I(2, 3)], d[2], t, d[4]); /* . [.] * -> * */
+ CHI_010_0(z->S[I(3, 3)], t, d[4], d[0]); /* . [.] * -> . */
+ CHI_101_0(z->S[I(4, 3)], d[4], d[0], d[1]); /* . * * -> . */
/* Last plane. Just y' = 4 to go. */
THETA_RHO(2, 3, 4, 0, 1);
- CHI_COMPL(t, b[1]); /* [*] */
- CHI_110_1(z->S[I(0, 4)], b[0], t, b[2]); /* * [*] . -> * */
- CHI_101_0(z->S[I(1, 4)], t, b[2], b[3]); /* [*] . * -> . */
- CHI_010_0(z->S[I(2, 4)], b[2], b[3], b[4]); /* . * . -> . */
- CHI_101_0(z->S[I(3, 4)], b[3], b[4], b[0]); /* * * . -> . */
- CHI_010_0(z->S[I(4, 4)], b[4], b[0], b[1]); /* * . . -> . */
+ CHI_COMPL(t, d[1]); /* [*] */
+ CHI_110_1(z->S[I(0, 4)], d[0], t, d[2]); /* * [*] . -> * */
+ CHI_101_0(z->S[I(1, 4)], t, d[2], d[3]); /* [*] . * -> . */
+ CHI_010_0(z->S[I(2, 4)], d[2], d[3], d[4]); /* . * . -> . */
+ CHI_101_0(z->S[I(3, 4)], d[3], d[4], d[0]); /* * * . -> . */
+ CHI_010_0(z->S[I(4, 4)], d[4], d[0], d[1]); /* * . . -> . */
/* And we're done. */
#undef THETA_RHO
--- /dev/null
+/* -*-c-*-
+ *
+ * AEAD schemes based on Salsa20/ChaCha and Poly1305
+ *
+ * (c) 2018 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef CATACOMB_LATINPOLY_DEF_H
+#define CATACOMB_LATINPOLY_DEF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+#include <mLib/buf.h>
+#include <mLib/sub.h>
+
+#ifndef CATACOMB_ARENA_H
+# include "arena.h"
+#endif
+
+#ifndef CATACOMB_CT_H
+# include "ct.h"
+#endif
+
+#ifndef CATACOMB_GAEAD_H
+# include "gaead.h"
+#endif
+
+#ifndef CATACOMB_KEYSZ_H
+# include "keysz.h"
+#endif
+
+#ifndef CATACOMB_LATINPOLY_H
+# include "latinpoly.h"
+#endif
+
+#ifndef CATACOMB_PARANOIA_H
+# include "paranoia.h"
+#endif
+
+#ifndef CATACOMB_POLY1305_H
+# include "poly1305.h"
+#endif
+
+#ifndef CATACOMB_SALSA20_H
+# include "salsa20.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct latinpoly_aad {
+ gaead_aad a;
+ poly1305_ctx poly;
+} latinpoly_aad;
+
+typedef struct latinpoly_key {
+ gaead_key k;
+ octet key[SALSA20_KEYSZ];
+ size_t ksz;
+} latinpoly_key;
+
+/*----- Common definitions ------------------------------------------------*/
+
+/* Tables. */
+extern const octet latinpoly_noncesz[], latinpoly_tagsz[];
+
+/* AAD methods. */
+extern void latinpoly_aadhash_poly1305(gaead_aad */*a*/,
+ const void */*h*/, size_t /*hsz*/);
+extern void latinpoly_aadhash_naclbox(gaead_aad */*a*/,
+ const void */*h*/, size_t /*hsz*/);
+extern void latinpoly_aaddestroy(gaead_aad */*a*/);
+
+/* Variants. */
+enum { LPVAR_NACLBOX, LPVAR_POLY1305 };
+
+/* --- @latinpoly_tag@ --- *
+ *
+ * Arguments: @const poly1305_ctx *aad@ = Poly1305 context hashing AAD
+ * @poly1305_ctx *ct@ = Poly1305 context hashing ciphertext
+ * @void *tag@ = where to write the tag
+ *
+ * Returns: ---
+ *
+ * Use: Completes a Latin-dance-Poly1305 tag, combining the AAD and
+ * ciphertext hashes, appending their lengths, and writing the
+ * final masked hash to @tag@. The @ct@ context is clobbered.
+ */
+
+extern void latinpoly_tag(const poly1305_ctx */*aad*/,
+ poly1305_ctx */*ct*/, void */*tag*/);
+
+/*----- Macros ------------------------------------------------------------*/
+
+#define LATINPOLY_DEF(latin, base, name) \
+ \
+/* Utilities. */ \
+ \
+/* Reinitialize the stream cipher and hash state given a new nonce. */ \
+static int reinit_##latin(x##latin##_ctx *ctx, int var, \
+ poly1305_ctx *aadpoly, poly1305_ctx *ctpoly, \
+ const void *n, size_t nsz) \
+{ \
+ poly1305_key pk; \
+ octet b[POLY1305_KEYSZ + POLY1305_MASKSZ]; \
+ \
+ switch (nsz) { \
+ case SALSA20_NONCESZ: \
+ memcpy(ctx->s.a, ctx->k, sizeof(ctx->k)); \
+ base##_setnonce(&ctx->s, n); \
+ break; \
+ case SALSA20_IETF_NONCESZ: \
+ memcpy(ctx->s.a, ctx->k, sizeof(ctx->k)); \
+ base##_setnonce_ietf(&ctx->s, n); \
+ break; \
+ case XSALSA20_NONCESZ: \
+ x##latin##_setnonce(ctx, n); \
+ break; \
+ default: \
+ return (-1); \
+ } \
+ \
+ latin##_encrypt(&ctx->s, 0, b, sizeof(b)); \
+ poly1305_keyinit(&pk, b, POLY1305_KEYSZ); \
+ poly1305_macinit(ctpoly, &pk, b + POLY1305_KEYSZ); \
+ switch (var) { \
+ case LPVAR_NACLBOX: \
+ aadpoly->count = 0; aadpoly->nbuf = 0; \
+ break; \
+ case LPVAR_POLY1305: \
+ poly1305_macinit(aadpoly, &pk, b + POLY1305_KEYSZ); \
+ latin##_encrypt(&ctx->s, 0, 0, SALSA20_OUTSZ - sizeof(b)); \
+ break; \
+ default: \
+ assert(0); \
+ } \
+ return (0); \
+} \
+ \
+/* AAD operations. */ \
+ \
+static const gaead_aadops gaops_##latin##_poly1305 = \
+ { &latin##_poly1305, 0, latinpoly_aadhash_poly1305, latinpoly_aaddestroy }; \
+ \
+static const gaead_aadops gaops_##latin##_naclbox = \
+ { &latin##_naclbox, 0, latinpoly_aadhash_naclbox, latinpoly_aaddestroy }; \
+ \
+/* Encryption operations. */ \
+ \
+typedef struct gectx_##latin { \
+ gaead_enc e; \
+ latinpoly_aad aad; \
+ x##latin##_ctx ctx; \
+ poly1305_ctx poly; \
+} gectx_##latin; \
+ \
+static gaead_aad *geaad_##latin(gaead_enc *e) \
+ { gectx_##latin *enc = (gectx_##latin *)e; return (&enc->aad.a); } \
+ \
+static int gereinit_##latin##_poly1305(gaead_enc *e, \
+ const void *n, size_t nsz, \
+ size_t hsz, size_t msz, size_t tsz) \
+{ \
+ gectx_##latin *enc = (gectx_##latin *)e; \
+ return (reinit_##latin(&enc->ctx, LPVAR_POLY1305, \
+ &enc->aad.poly, &enc->poly, n, nsz)); \
+} \
+ \
+static int gereinit_##latin##_naclbox(gaead_enc *e, \
+ const void *n, size_t nsz, \
+ size_t hsz, size_t msz, size_t tsz) \
+{ \
+ gectx_##latin *enc = (gectx_##latin *)e; \
+ return (reinit_##latin(&enc->ctx, LPVAR_NACLBOX, \
+ &enc->aad.poly, &enc->poly, n, nsz)); \
+} \
+ \
+static int geenc_##latin(gaead_enc *e, \
+ const void *m, size_t msz, buf *b) \
+{ \
+ gectx_##latin *enc = (gectx_##latin *)e; \
+ void *q; \
+ \
+ if (msz) { q = buf_get(b, msz); if (!q) return (-1); } \
+ else q = 0; \
+ latin##_encrypt(&enc->ctx.s, m, q, msz); \
+ poly1305_hash(&enc->poly, q, msz); \
+ return (0); \
+} \
+ \
+static int gedone_##latin##_common(gectx_##latin *enc, \
+ const latinpoly_aad *aad, \
+ buf *b, size_t tsz) \
+{ \
+ if (tsz != POLY1305_TAGSZ) return (-1); \
+ assert((!enc->aad.poly.count && !enc->aad.poly.nbuf && !aad) || \
+ aad == &enc->aad); \
+ if (!BOK(b)) return (-1); \
+ return (0); \
+} \
+ \
+static int gedone_##latin##_poly1305(gaead_enc *e, const gaead_aad *a, \
+ buf *b, void *t, size_t tsz) \
+{ \
+ gectx_##latin *enc = (gectx_##latin *)e; \
+ const latinpoly_aad *aad = (const latinpoly_aad *)a; \
+ \
+ if (gedone_##latin##_common(enc, aad, b, tsz)) return (-1); \
+ latinpoly_tag(aad ? &aad->poly : 0, &enc->poly, t); \
+ return (0); \
+} \
+ \
+static int gedone_##latin##_naclbox(gaead_enc *e, const gaead_aad *a, \
+ buf *b, void *t, size_t tsz) \
+{ \
+ gectx_##latin *enc = (gectx_##latin *)e; \
+ const latinpoly_aad *aad = (const latinpoly_aad *)a; \
+ \
+ if (gedone_##latin##_common(enc, aad, b, tsz)) return (-1); \
+ poly1305_done(&enc->poly, t); \
+ return (0); \
+} \
+ \
+static void gedestroy_##latin(gaead_enc *e) \
+ { gectx_##latin *enc = (gectx_##latin *)e; BURN(*enc); S_DESTROY(enc); } \
+ \
+static gaead_encops geops_##latin##_poly1305 = \
+ { &latin##_poly1305, geaad_##latin, gereinit_##latin##_poly1305, \
+ geenc_##latin, gedone_##latin##_poly1305, gedestroy_##latin }; \
+ \
+static gaead_encops geops_##latin##_naclbox = \
+ { &latin##_naclbox, geaad_##latin, gereinit_##latin##_naclbox, \
+ geenc_##latin, gedone_##latin##_naclbox, gedestroy_##latin }; \
+ \
+/* Decryption operations. */ \
+ \
+typedef struct gdctx_##latin { \
+ gaead_dec d; \
+ latinpoly_aad aad; \
+ x##latin##_ctx ctx; \
+ poly1305_ctx poly; \
+} gdctx_##latin; \
+ \
+static gaead_aad *gdaad_##latin(gaead_dec *d) \
+ { gdctx_##latin *dec = (gdctx_##latin *)d; return (&dec->aad.a); } \
+ \
+static int gdreinit_##latin##_poly1305(gaead_dec *d, \
+ const void *n, size_t nsz, \
+ size_t hsz, size_t msz, size_t tsz) \
+{ \
+ gdctx_##latin *dec = (gdctx_##latin *)d; \
+ return (reinit_##latin(&dec->ctx, LPVAR_POLY1305, \
+ &dec->aad.poly, &dec->poly, n, nsz)); \
+} \
+ \
+static int gdreinit_##latin##_naclbox(gaead_dec *d, \
+ const void *n, size_t nsz, \
+ size_t hsz, size_t msz, size_t tsz) \
+{ \
+ gdctx_##latin *dec = (gdctx_##latin *)d; \
+ return (reinit_##latin(&dec->ctx, LPVAR_NACLBOX, \
+ &dec->aad.poly, &dec->poly, n, nsz)); \
+} \
+ \
+static int gddec_##latin(gaead_dec *d, \
+ const void *c, size_t csz, buf *b) \
+{ \
+ gdctx_##latin *dec = (gdctx_##latin *)d; \
+ void *q; \
+ \
+ if (csz) { q = buf_get(b, csz); if (!q) return (-1); } \
+ else q = 0; \
+ poly1305_hash(&dec->poly, c, csz); \
+ latin##_encrypt(&dec->ctx.s, c, q, csz); \
+ return (0); \
+} \
+ \
+static int gddone_##latin##_common(gdctx_##latin *dec, \
+ const latinpoly_aad *aad, \
+ buf *b, size_t tsz) \
+{ \
+ if (tsz != POLY1305_TAGSZ) return (-1); \
+ assert((!dec->aad.poly.count && !dec->aad.poly.nbuf && !aad) || \
+ aad == &dec->aad); \
+ if (!BOK(b)) return (-1); \
+ return (0); \
+} \
+ \
+static int gddone_##latin##_poly1305(gaead_dec *d, const gaead_aad *a, \
+ buf *b, const void *t, size_t tsz) \
+{ \
+ gdctx_##latin *dec = (gdctx_##latin *)d; \
+ const latinpoly_aad *aad = (const latinpoly_aad *)a; \
+ octet u[POLY1305_TAGSZ]; \
+ \
+ if (gddone_##latin##_common(dec, aad, b, tsz)) return (-1); \
+ latinpoly_tag(aad ? &aad->poly : 0, &dec->poly, u); \
+ if (ct_memeq(t, u, POLY1305_TAGSZ)) return (+1); \
+ else return (0); \
+} \
+ \
+static int gddone_##latin##_naclbox(gaead_dec *d, const gaead_aad *a, \
+ buf *b, const void *t, size_t tsz) \
+{ \
+ gdctx_##latin *dec = (gdctx_##latin *)d; \
+ const latinpoly_aad *aad = (const latinpoly_aad *)a; \
+ octet u[POLY1305_TAGSZ]; \
+ \
+ if (gddone_##latin##_common(dec, aad, b, tsz)) return (-1); \
+ poly1305_done(&dec->poly, u); \
+ if (ct_memeq(t, u, POLY1305_TAGSZ)) return (+1); \
+ else return (0); \
+} \
+ \
+static void gddestroy_##latin(gaead_dec *d) \
+ { gdctx_##latin *dec = (gdctx_##latin *)d; BURN(*dec); S_DESTROY(dec); } \
+ \
+static gaead_decops gdops_##latin##_poly1305 = \
+ { &latin##_poly1305, gdaad_##latin, gdreinit_##latin##_poly1305, \
+ gddec_##latin, gddone_##latin##_poly1305, gddestroy_##latin }; \
+ \
+static gaead_decops gdops_##latin##_naclbox = \
+ { &latin##_poly1305, gdaad_##latin, gdreinit_##latin##_naclbox, \
+ gddec_##latin, gddone_##latin##_naclbox, gddestroy_##latin }; \
+ \
+/* Key operations. */ \
+ \
+static gaead_enc *gkenc_##latin##_poly1305(const gaead_key *k, \
+ const void *n, size_t nsz, \
+ size_t hsz, size_t msz, \
+ size_t tsz) \
+{ \
+ latinpoly_key *key = (latinpoly_key *)k; \
+ gectx_##latin *enc = S_CREATE(gectx_##latin); \
+ \
+ enc->e.ops = &geops_##latin##_poly1305; \
+ enc->aad.a.ops = &gaops_##latin##_poly1305; \
+ x##latin##_init(&enc->ctx, key->key, key->ksz, 0); \
+ if (reinit_##latin(&enc->ctx, LPVAR_POLY1305, \
+ &enc->aad.poly, &enc->poly, n, nsz)) \
+ { gedestroy_##latin(&enc->e); return (0); } \
+ return (&enc->e); \
+} \
+ \
+static gaead_enc *gkenc_##latin##_naclbox(const gaead_key *k, \
+ const void *n, size_t nsz, \
+ size_t hsz, size_t msz, \
+ size_t tsz) \
+{ \
+ latinpoly_key *key = (latinpoly_key *)k; \
+ gectx_##latin *enc = S_CREATE(gectx_##latin); \
+ \
+ enc->e.ops = &geops_##latin##_naclbox; \
+ enc->aad.a.ops = &gaops_##latin##_naclbox; \
+ x##latin##_init(&enc->ctx, key->key, key->ksz, 0); \
+ if (reinit_##latin(&enc->ctx, LPVAR_NACLBOX, \
+ &enc->aad.poly, &enc->poly, n, nsz)) \
+ { gedestroy_##latin(&enc->e); return (0); } \
+ return (&enc->e); \
+} \
+ \
+static gaead_dec *gkdec_##latin##_poly1305(const gaead_key *k, \
+ const void *n, size_t nsz, \
+ size_t hsz, size_t msz, \
+ size_t tsz) \
+{ \
+ latinpoly_key *key = (latinpoly_key *)k; \
+ gdctx_##latin *dec = S_CREATE(gdctx_##latin); \
+ \
+ dec->d.ops = &gdops_##latin##_poly1305; \
+ dec->aad.a.ops = &gaops_##latin##_poly1305; \
+ x##latin##_init(&dec->ctx, key->key, key->ksz, 0); \
+ if (reinit_##latin(&dec->ctx, LPVAR_POLY1305, \
+ &dec->aad.poly, &dec->poly, n, nsz)) \
+ { gddestroy_##latin(&dec->d); return (0); } \
+ return (&dec->d); \
+} \
+ \
+static gaead_dec *gkdec_##latin##_naclbox(const gaead_key *k, \
+ const void *n, size_t nsz, \
+ size_t hsz, size_t msz, \
+ size_t tsz) \
+{ \
+ latinpoly_key *key = (latinpoly_key *)k; \
+ gdctx_##latin *dec = S_CREATE(gdctx_##latin); \
+ \
+ dec->d.ops = &gdops_##latin##_naclbox; \
+ dec->aad.a.ops = &gaops_##latin##_naclbox; \
+ x##latin##_init(&dec->ctx, key->key, key->ksz, 0); \
+ if (reinit_##latin(&dec->ctx, LPVAR_NACLBOX, \
+ &dec->aad.poly, &dec->poly, n, nsz)) \
+ { gddestroy_##latin(&dec->d); return (0); } \
+ return (&dec->d); \
+} \
+ \
+static void gkdestroy_##latin(gaead_key *k) \
+ { latinpoly_key *key = (latinpoly_key *)k; BURN(*key); S_DESTROY(key); } \
+ \
+static const gaead_keyops gkops_##latin##_poly1305 = \
+ { &latin##_poly1305, 0, \
+ gkenc_##latin##_poly1305, gkdec_##latin##_poly1305, \
+ gkdestroy_##latin }; \
+ \
+static const gaead_keyops gkops_##latin##_naclbox = \
+ { &latin##_naclbox, 0, \
+ gkenc_##latin##_naclbox, gkdec_##latin##_naclbox, \
+ gkdestroy_##latin }; \
+ \
+/* Class definition. */ \
+ \
+static gaead_key *gkey_##latin##_common(const gaead_keyops *ops, \
+ const void *k, size_t ksz) \
+{ \
+ latinpoly_key *key = S_CREATE(latinpoly_key); \
+ \
+ key->k.ops = ops; \
+ KSZ_ASSERT(latin, ksz); memcpy(key->key, k, ksz); key->ksz = ksz; \
+ return (&key->k); \
+} \
+ \
+static gaead_key *gkey_##latin##_poly1305(const void *k, size_t ksz) \
+ { return (gkey_##latin##_common(&gkops_##latin##_poly1305, k, ksz)); } \
+ \
+static gaead_key *gkey_##latin##_naclbox(const void *k, size_t ksz) \
+ { return (gkey_##latin##_common(&gkops_##latin##_naclbox, k, ksz)); } \
+ \
+const gcaead latin##_poly1305 = { \
+ name "-poly1305", latin##_keysz, latinpoly_noncesz, latinpoly_tagsz, \
+ 64, 0, 0, AEADF_AADNDEP, \
+ gkey_##latin##_poly1305 \
+}; \
+ \
+const gcaead latin##_naclbox = { \
+ name "-naclbox", latin##_keysz, latinpoly_noncesz, latinpoly_tagsz, \
+ 64, 0, 0, AEADF_AADNDEP | AEADF_NOAAD, \
+ gkey_##latin##_naclbox \
+};
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
--- /dev/null
+/* -*-c-*-
+ *
+ * Testing for AEAD schemes based on Salsa20/ChaCha and Poly1305
+ *
+ * (c) 2018 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "latinpoly-def.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @latinpoly_test@ --- *
+ *
+ * Arguments: @gcaead *aec@ = authenticated encryption class to test
+ * @dstr *v@ = pointer to test-vector
+ *
+ * Returns: Nonzero if the test passed, zero on failure.
+ */
+
+int latinpoly_test(const gcaead *aec, dstr *v)
+{
+ gaead_key *k;
+ gaead_aad *a;
+ gaead_enc *e; gaead_dec *d;
+ dstr out = DSTR_INIT, tag = DSTR_INIT;
+ buf b;
+ int rc;
+ int ok = 1;
+
+ k = GAEAD_KEY(aec, v[0].buf, v[0].len);
+
+ dstr_reset(&out); dstr_ensure(&out, v[3].len);
+ dstr_reset(&tag); dstr_ensure(&tag, POLY1305_TAGSZ);
+ e = GAEAD_ENC(k, v[1].buf, v[1].len, 0, 0, 0);
+ a = GAEAD_AAD(e); GAEAD_HASH(a, v[2].buf, v[2].len);
+ buf_init(&b, out.buf, out.sz);
+ rc = GAEAD_ENCRYPT(e, v[3].buf, v[3].len, &b);
+ if (rc) { printf("!! encrypt reports failure\n"); goto encfail; }
+ rc = GAEAD_DONE(e, a, &b, tag.buf, POLY1305_TAGSZ);
+ if (rc) { printf("!! encryptdone reports failure\n"); goto encfail; }
+
+ out.len = BLEN(&b); tag.len = POLY1305_TAGSZ;
+ if (out.len != v[4].len || memcmp(out.buf, v[4].buf, v[4].len) ||
+ memcmp(tag.buf, v[5].buf, v[5].len)) {
+ encfail:
+ ok = 0;
+ printf("\n%s encrypt FAILED", aec->name);
+ printf("\n key = "); type_hex.dump(&v[0], stdout);
+ printf("\n nonce = "); type_hex.dump(&v[1], stdout);
+ printf("\n header = "); type_hex.dump(&v[2], stdout);
+ printf("\n message = "); type_hex.dump(&v[3], stdout);
+ printf("\n exp ct = "); type_hex.dump(&v[4], stdout);
+ printf("\n calc ct = "); type_hex.dump(&out, stdout);
+ printf("\n exp tag = "); type_hex.dump(&v[5], stdout);
+ printf("\ncalc tag = "); type_hex.dump(&tag, stdout);
+ putchar('\n');
+ }
+ GAEAD_DESTROY(a);
+ GAEAD_DESTROY(e);
+
+ dstr_reset(&out); dstr_ensure(&out, v[3].len);
+ dstr_reset(&tag); dstr_ensure(&tag, POLY1305_TAGSZ);
+ d = GAEAD_DEC(k, v[1].buf, v[1].len, 0, 0, 0);
+ a = GAEAD_AAD(d); GAEAD_HASH(a, v[2].buf, v[2].len);
+ buf_init(&b, out.buf, out.sz);
+ rc = GAEAD_DECRYPT(d, v[4].buf, v[4].len, &b);
+ if (rc) { printf("!! decrypt reports failure\n"); goto decfail; }
+ rc = GAEAD_DONE(e, a, &b, v[5].buf, POLY1305_TAGSZ);
+ if (rc < 0) { printf("!! decryptdone reports failure\n"); goto decfail; }
+
+ out.len = BLEN(&b); tag.len = POLY1305_TAGSZ;
+ if (out.len != v[3].len || memcmp(out.buf, v[3].buf, v[3].len) || !rc) {
+ decfail:
+ ok = 0;
+ printf("\ndecrypt FAILED");
+ printf("\n key = "); type_hex.dump(&v[0], stdout);
+ printf("\n nonce = "); type_hex.dump(&v[1], stdout);
+ printf("\n header = "); type_hex.dump(&v[2], stdout);
+ printf("\n cipher = "); type_hex.dump(&v[4], stdout);
+ printf("\n exp msg = "); type_hex.dump(&v[3], stdout);
+ printf("\ncalc msg = "); type_hex.dump(&out, stdout);
+ printf("\n tag = "); type_hex.dump(&v[5], stdout);
+ printf("\n verify %s", rc > 0 ? "ok" : "FAILED");
+ putchar('\n');
+ }
+ GAEAD_DESTROY(a);
+ GAEAD_DESTROY(d);
+
+ GAEAD_DESTROY(k);
+ dstr_destroy(&out); dstr_destroy(&tag);
+ return (ok);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
--- /dev/null
+/* -*-c-*-
+ *
+ * Testing for AEAD schemes based on Salsa20/ChaCha and Poly1305
+ *
+ * (c) 2018 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef CATACOMB_LATINPOLY_TEST_H
+#define CATACOMB_LATINPOLY_TEST_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/dstr.h>
+#include <mLib/testrig.h>
+
+#ifndef CATACOMB_GAEAD_H
+# include "gaead.h"
+#endif
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @latinpoly_test@ --- *
+ *
+ * Arguments: @gcaead *aec@ = authenticated encryption class to test
+ * @dstr *v@ = pointer to test-vector
+ *
+ * Returns: Nonzero if the test passed, zero on failure.
+ *
+ * Use: Checks a test vector. This internal function is not
+ * available outside of Catacomb's build tree.
+ */
+
+extern int latinpoly_test(const gcaead */*aec*/, dstr */*v*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
--- /dev/null
+/* -*-c-*-
+ *
+ * AEAD schemes based on Salsa20/ChaCha and Poly1305
+ *
+ * (c) 2018 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "config.h"
+
+#include <mLib/bits.h>
+#include <mLib/buf.h>
+
+#include "gaead.h"
+#include "keysz.h"
+#include "latinpoly-def.h"
+
+#include "poly1305.h"
+#include "salsa20.h"
+
+/*----- Common definitions ------------------------------------------------*/
+
+const octet
+ latinpoly_noncesz[] = { KSZ_SET, SALSA20_NONCESZ, SALSA20_IETF_NONCESZ,
+ XSALSA20_NONCESZ, 0 },
+ latinpoly_tagsz[] = { KSZ_SET, POLY1305_TAGSZ, 0 };
+
+/* AAD handling. */
+
+void latinpoly_aadhash_poly1305(gaead_aad *a, const void *h, size_t hsz)
+{
+ latinpoly_aad *aad = (latinpoly_aad *)a;
+ poly1305_hash(&aad->poly, h, hsz);
+}
+
+void latinpoly_aadhash_naclbox(gaead_aad *a, const void *h, size_t hsz)
+ { assert(!hsz); }
+
+void latinpoly_aaddestroy(gaead_aad *a) { ; }
+
+/* --- @latinpoly_tag@ --- *
+ *
+ * Arguments: @const poly1305_ctx *aad@ = Poly1305 context hashing AAD
+ * @poly1305_ctx *ct@ = Poly1305 context hashing ciphertext
+ * @void *tag@ = where to write the tag
+ *
+ * Returns: ---
+ *
+ * Use: Completes a Latin-dance-Poly1305 tag, combining the AAD and
+ * ciphertext hashes, appending their lengths, and writing the
+ * final masked hash to @tag@. The @ct@ context is clobbered.
+ */
+
+/* Write the length of data pushed through Poly1305 as a 64-bit integer. */
+static void putlen(octet *p, const poly1305_ctx *poly)
+{
+ uint32 lo = U32((poly->count << 4) | poly->nbuf),
+ hi = U32(poly->count >> 28);
+ STORE32_L(p + 0, lo); STORE32_L(p + 4, hi);
+}
+
+void latinpoly_tag(const poly1305_ctx *aad, poly1305_ctx *ct, void *tag)
+{
+ octet b[16];
+ poly1305_ctx t;
+
+ putlen(b + 8, ct); poly1305_flushzero(ct);
+ if (!aad) memset(b, 0, 8);
+ else {
+ putlen(b + 0, aad);
+ t = *aad; poly1305_flushzero(&t); poly1305_concat(ct, &t, ct);
+ }
+ poly1305_hash(ct, b, 16); poly1305_done(ct, tag);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
--- /dev/null
+/* -*-c-*-
+ *
+ * AEAD schemes based on Salsa20/ChaCha and Poly1305
+ *
+ * (c) 2018 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*----- Notes on this construction ----------------------------------------*
+ *
+ * The AEAD class @chacha20_poly1305@ with a 96-bit nonce is exactly the
+ * scheme specified in RFC7539. This implementation extends that
+ * specification in two ways:
+ *
+ * * It permits ciphers other than ChaCha20: specifically ChaCha%$r$% and
+ * Salsa20/%$r$% with %$r \in \{ 8, 12, 20 \}$%.
+ *
+ * * It allows nonces of 64, 96, and 192 bits. A 64-bit nonce matches
+ * Bernstein's original specification of Salsa20 and ChaCha; the 96-bit
+ * nonce matches RFC7539; and the 192-bit nonce matches Bernstein's
+ * XSalsa20. The implementation uses XSalsa20 or XChaCha as appropriate
+ * automatically based on the provided nonce length.
+ *
+ * These extensions do not significantly affect Procter's security analysis
+ * except that an application should not mix nonce sizes with the same key.
+ * (It is possible to do this safely, but it requires detailed understanding
+ * of how everything fits together and isn't worth the effort.)
+ *
+ * The @salsa20_naclbox@ with a 192-bit nonce is exactly the scheme
+ * implemented in Bernstein's `NaCl' library as @crypto_secretbox@, except
+ * that it's flexible regarding tag placement rather than insisting on
+ * prefixing it to the ciphertext. Unlike NaCl, we provide a restartable
+ * interface, and allow the use of other ciphers and nonce lengths.
+ */
+
+#ifndef CATACOMB_LATINPOLY_H
+#define CATACOMB_LATINPOLY_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#ifndef CATACOMB_GAEAD_H
+# include "gaead.h"
+#endif
+
+/*----- Definitions -------------------------------------------------------*/
+
+extern const gcaead
+ chacha20_poly1305, chacha12_poly1305, chacha8_poly1305,
+ chacha20_naclbox, chacha12_naclbox, chacha8_naclbox,
+ salsa20_poly1305, salsa2012_poly1305, salsa208_poly1305,
+ salsa20_naclbox, salsa2012_naclbox, salsa208_naclbox;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
*/ \
\
void pre##_mgfkeybegin(pre##_mgfctx *k) \
-{ \
- k->c = 0; \
- k->bsz = 0; \
- pre##_init(&k->k); \
-} \
+ { k->c = 0; k->off = 0; pre##_init(&k->k); } \
\
void pre##_mgfkeyadd(pre##_mgfctx *k, const void *p, size_t sz) \
-{ \
- pre##_hash(&k->k, p, sz); \
-} \
+ { pre##_hash(&k->k, p, sz); } \
\
/* ---- @pre_mgfinit@ --- * \
* \
*/ \
\
void pre##_mgfinit(pre##_mgfctx *k, const void *p, size_t sz) \
-{ \
- k->c = 0; \
- k->bsz = 0; \
- pre##_init(&k->k); \
- pre##_hash(&k->k, p, sz); \
-} \
+ { k->c = 0; k->off = 0; pre##_init(&k->k); pre##_hash(&k->k, p, sz); } \
\
/* --- @pre_mgfencrypt@ --- * \
* \
void pre##_mgfencrypt(pre##_mgfctx *k, const void *s, \
void *d, size_t sz) \
{ \
+ pre##_ctx h; \
const octet *ss = s; \
octet *dd = d; \
+ const octet *p; \
+ size_t off; \
\
/* --- Empty the buffer if there's anything there --- */ \
\
- if (k->bsz) { \
- const octet *p = k->buf + PRE##_HASHSZ - k->bsz; \
- size_t n = sz > k->bsz ? k->bsz : sz; \
- sz -= n; \
- k->bsz -= n; \
- if (dd) { \
- if (!ss) { \
- memcpy(dd, p, n); \
- dd += n; \
- } else { \
- while (n) { \
- *dd++ = *ss++ ^ *p++; \
- n--; \
- } \
- } \
- } \
+ if (k->off) { \
+ p = k->b + PRE##_HASHSZ - k->off; \
+ off = sz > k->off ? k->off : sz; \
+ sz -= off; k->off -= off; \
+ if (!dd) /* do nothing */; \
+ else if (!ss) { memcpy(dd, p, off); dd += off; } \
+ else while (off--) *dd++ = *ss++ ^ *p++; \
} \
\
/* --- While necessary, generate some more mask --- */ \
\
while (sz) { \
- pre##_ctx c = k->k; /* Not quick! */ \
- size_t n; \
- \
- STORE32(k->buf, k->c); \
- k->c++; \
- pre##_hash(&c, k->buf, 4); \
- pre##_done(&c, k->buf); \
- n = sz > PRE##_HASHSZ ? PRE##_HASHSZ : sz; \
- k->bsz = PRE##_HASHSZ - n; \
- sz -= n; \
- if (dd) { \
- const octet *p = k->buf; \
- if (!ss) { \
- memcpy(dd, p, n); \
- dd += n; \
- } else { \
- while (n) { \
- *dd++ = *ss++ ^ *p++; \
- n--; \
- } \
- } \
- } \
+ STORE32(k->b, k->c); k->c++; \
+ h = k->k; pre##_hash(&h, k->b, 4); pre##_done(&h, k->b); \
+ off = sz > PRE##_HASHSZ ? PRE##_HASHSZ : sz; \
+ k->off = PRE##_HASHSZ - off; \
+ sz -= off; \
+ p = k->b; \
+ if (!dd) /* do nothing */; \
+ else if (!ss) { memcpy(dd, p, off); dd += off; } \
+ else while (off--) *dd++ = *ss++ ^ *p++; \
} \
} \
\
*/ \
\
void pre##_mgfsetindex(pre##_mgfctx *k, uint32 c) \
-{ \
- k->c = c; \
- k->bsz = 0; \
-} \
+ { k->c = c; k->off = 0; } \
\
/* --- Generic cipher interface --- */ \
\
} \
\
static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) \
-{ \
- gctx *g = (gctx *)c; \
- pre##_mgfencrypt(&g->k, s, t, sz); \
-} \
+ { gctx *g = (gctx *)c; pre##_mgfencrypt(&g->k, s, t, sz); } \
\
static void gdestroy(gcipher *c) \
-{ \
- gctx *g = (gctx *)c; \
- BURN(*g); \
- S_DESTROY(g); \
-} \
+ { gctx *g = (gctx *)c; BURN(*g); S_DESTROY(g); } \
\
static const gcipher_ops gops = { \
&pre##_mgf, \
} \
\
static void grfill(grand *r, void *p, size_t sz) \
-{ \
- grctx *g = (grctx *)r; \
- pre##_mgfencrypt(&g->k, 0, p, sz); \
-} \
+ { grctx *g = (grctx *)r; pre##_mgfencrypt(&g->k, 0, p, sz); } \
\
static const grand_ops grops = { \
name "-mgf", \
#ifdef TEST_RIG
-#include <stdio.h>
-
-#include "daftstory.h"
+#include "modes-test.h"
/* --- @MGF_TEST@ --- *
*
#define MGF_TESTX(PRE, pre, name, fname) \
\
-/* --- Initial plaintext for the test --- */ \
- \
-static const octet text[] = TEXT; \
+static pre##_mgfctx ctx; \
\
-/* --- Key and IV to use --- */ \
+static void pre##_mgf_test_setup(const octet *k, size_t ksz) \
+ { pre##_mgfinit(&ctx, k, ksz); } \
\
-static const octet key[] = KEY; \
+static void pre##_mgf_test_reset(const octet *iv) \
+ { pre##_mgfsetindex(&ctx, 0); } \
\
-/* --- Buffers for encryption and decryption output --- */ \
+static void pre##_mgf_test_enc(const octet *s, octet *d, size_t sz) \
+ { pre##_mgfencrypt(&ctx, s, d, sz); } \
\
-static octet ct[sizeof(text)]; \
-static octet pt[sizeof(text)]; \
- \
-static void hexdump(const octet *p, size_t sz) \
+int main(int argc, char *argv[]) \
{ \
- const octet *q = p + sz; \
- for (sz = 0; p < q; p++, sz++) { \
- printf("%02x", *p); \
- if ((sz + 1) % PRE##_HASHSZ == 0) \
- putchar(':'); \
- } \
-} \
- \
-int main(void) \
-{ \
- size_t sz = 0, rest; \
- pre##_mgfctx ctx; \
- int status = 0; \
- int done = 0; \
- \
- size_t keysz = strlen((const char *)key); \
- \
- fputs(name "-mgf: ", stdout); \
- \
- pre##_mgfinit(&ctx, key, keysz); \
- \
- while (sz <= sizeof(text)) { \
- rest = sizeof(text) - sz; \
- memcpy(ct, text, sizeof(text)); \
- pre##_mgfsetindex(&ctx, 0); \
- pre##_mgfencrypt(&ctx, ct, ct, sz); \
- pre##_mgfencrypt(&ctx, ct + sz, ct + sz, rest); \
- memcpy(pt, ct, sizeof(text)); \
- pre##_mgfsetindex(&ctx, 0); \
- pre##_mgfencrypt(&ctx, pt, pt, rest); \
- pre##_mgfencrypt(&ctx, pt + rest, pt + rest, sz); \
- if (memcmp(pt, text, sizeof(text)) == 0) { \
- done++; \
- if (sizeof(text) < 40 || done % 8 == 0) \
- fputc('.', stdout); \
- if (done % 480 == 0) \
- fputs("\n\t", stdout); \
- fflush(stdout); \
- } else { \
- printf("\nError (sz = %lu)\n", (unsigned long)sz); \
- status = 1; \
- printf("\tplaintext = "); hexdump(text, sz); \
- printf(", "); hexdump(text + sz, rest); \
- fputc('\n', stdout); \
- printf("\tciphertext = "); hexdump(ct, sz); \
- printf(", "); hexdump(ct + sz, rest); \
- fputc('\n', stdout); \
- printf("\trecovered text = "); hexdump(pt, sz); \
- printf(", "); hexdump(pt + sz, rest); \
- fputc('\n', stdout); \
- fputc('\n', stdout); \
- } \
- if (sz < 63) \
- sz++; \
- else \
- sz += 9; \
- } \
- \
- fputs(status ? " failed\n" : " ok\n", stdout); \
- return (status); \
+ return test_encmode(fname "-mgf", 0, PRE##_HASHSZ, 1, 0, \
+ pre##_mgf_test_setup, pre##_mgf_test_reset, \
+ pre##_mgf_test_enc, pre##_mgf_test_enc, \
+ argc, argv); \
}
#else
typedef struct pre##_mgfctx { \
pre##_ctx k; /* Underlying key context */ \
uint32 c; /* Counter */ \
- octet buf[PRE##_HASHSZ]; /* Output buffer */ \
- size_t bsz; /* Size of buffered data */ \
+ octet b[PRE##_HASHSZ]; /* Output buffer */ \
+ unsigned off; /* Size of buffered data */ \
} pre##_mgfctx; \
\
/* --- Other useful constants --- */ \
--- /dev/null
+/* -*-c-*-
+ *
+ * Common code for testing encryption modes
+ *
+ * (c) 2018 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <unistd.h>
+
+#include <mLib/alloc.h>
+#include <mLib/bits.h>
+#include <mLib/dstr.h>
+#include <mLib/quis.h>
+#include <mLib/report.h>
+
+#include "modes-test.h"
+
+/*----- The reference data ------------------------------------------------*/
+
+#ifdef SMALL_TEST
+static const octet text[] = "A small piece of text for testing encryption.";
+#else
+#define STORY "\
+Once upon a time there were a beautiful princess, a slightly nutty wizard,\n\
+and a watermelon. Now, the watermelon had decided that it probably wasn't\n\
+going to get very far with the princess unless it did something pretty\n\
+drastic. So it asked the wizard to turn it into a handsome prince.\n\
+\n\
+At least, this is the way that the wizard viewed the situation. He might\n\
+have just hallucinated it all; those mushrooms had looked ever so nice.\n\
+\n\
+Back to the point. The watermelon had expressed its desire not to be a\n\
+watermelon any more. And the wizard was probably tripping something quite\n\
+powerful. He hunted around a bit for his staff, and mumbled something\n\
+that film directors would think of as sounding appropriately arcane and\n\
+mystical (but was, in fact, just the ingredients list for an ancient\n\
+remedy for athlete's foot) and *pop*. Cooked watermelon. Yuk.\n\
+\n\
+Later in the year, the princess tripped over the hem of her dress, fell\n\
+down a spiral staircase, and died. The king ordered dressmakers to attach\n\
+safety warnings to long dresses.\n\
+\n\
+And the wizard? Who cares?\n\
+"
+static const octet text[] = STORY STORY;
+#endif
+
+#define TEXTSZ (sizeof(text))
+
+static const octet key[] = "Penguins rule OK, rhubarb cauliflower",
+ iv[] = "EdgewareCatacomb, parsley, sage, rosemary and thyme";
+
+/*----- Static variables --------------------------------------------------*/
+
+/* Encryption buffers, for ciphertext, recovered plaintext, and consistency
+ * reference.
+ */
+static octet ct[TEXTSZ], pt[TEXTSZ], ref[TEXTSZ];
+
+/* A resizeable buffer for verifying regression data. */
+static octet *t = 0; size_t tsz = 0;
+
+/*----- Diagnostic utilities ----------------------------------------------*/
+
+/* Print the @sz@-byte buffer @p@, beginning at offset @off@ within some
+ * larger buffer, marking block boundaries every @blksz@ bytes.
+ */
+static void hexdump(const octet *p, size_t sz, size_t off, size_t blksz)
+{
+ const octet *q = p + sz;
+ for (sz = 0; p < q; p++, sz++) {
+ printf("%02x", *p);
+ if ((off + sz + 1)%blksz == 0) putchar(':');
+ }
+}
+
+/* Print the buffer @p@, labelling it as @what@, splitting it into three
+ * pieces of sizes @sz0@, @sz1@, and @sz2@ respectively. Block boundaries
+ * every @blksz@ bytes are shown consistency, independent of the split
+ * positions.
+ */
+static void dump_split(const char *what, size_t blksz, const octet *p,
+ size_t sz0, size_t sz1, size_t sz2)
+{
+ printf("\t%-16s = ", what);
+ hexdump(p, sz0, 0, blksz);
+ if (sz1) { printf(", "); hexdump(p + sz0, sz1, sz0, blksz); }
+ if (sz2) { printf(", "); hexdump(p + sz0 + sz1, sz2, sz0 + sz1, blksz); }
+ fputc('\n', stdout);
+}
+
+/*----- Regression-data utilities -----------------------------------------*/
+
+/* Regression modes. We can @CHECK@ existing data, @RECORD@ new data, or
+ * @IGNORE@ the regression testing entirely.
+ */
+enum { IGNORE, RECORD, CHECK };
+
+/* Read or write regression data from/to @fp@ according to @rmode@. The data
+ * item is described as @what@ in diagnostic messages, and consists of @sz@
+ * bytes beginning at @p@.
+ *
+ * If @rmode@ is @IGNORE@, then this function does nothing; if @rmode@ is
+ * @RECORD@, then it writes @p@ to the output file with some framing; and if
+ * @rmode@ is @CHECK@ then it checks that the next chunk of data from the
+ * file matches @p@.
+ *
+ * Returns zero if all is well or @-1@ on a mismatch; I/O errors are fatal.
+ *
+ * Framing is trivial and consists of a 4-byte big-endian non-inclusive
+ * length prepended to each buffer. No padding is written to maintain
+ * alignment.
+ */
+static int regress_data(int rmode, FILE *fp, const char *what,
+ const void *p, size_t sz)
+{
+ octet b[4];
+ size_t psz;
+
+ switch (rmode) {
+ case IGNORE:
+ return (0);
+ case RECORD:
+ STORE32(b, sz);
+ if (!fwrite(b, 4, 1, fp) || !fwrite(p, sz, 1, fp))
+ die(1, "failed to write %s: %s", what, strerror(errno));
+ return (0);
+ case CHECK:
+ if (!fread(b, 4, 1, fp))
+ die(1, "failed to read %s length: %s", what,
+ ferror(fp) ? strerror(errno) : "unexpected eof");
+ psz = LOAD32(b);
+ if (psz != sz)
+ die(1, "incorrect %s length (%lu /= %lu; sync failure?)",
+ what, (unsigned long)psz, (unsigned long)sz);
+ if (tsz < sz) { xfree(t); t = xmalloc(sz); tsz = sz; }
+ if (!fread(t, sz, 1, fp))
+ die(1, "failed to read %s: %s", what,
+ ferror(fp) ? strerror(errno) : "unexpected eof");
+ if (memcmp(p, t, sz) != 0) return (-1);
+ return (0);
+ default:
+ abort();
+ }
+}
+
+/* Read or write framing data from/to @fp@ according to @rmode@. The framing
+ * item is describd as @what@ in diagnostic messages, and consists of @sz@
+ * bytes beginning at @p@.
+ *
+ * Framing data is used to verify that a recorded regression-data file is
+ * still appropriate for use. A fatal error is reported on any kind of
+ * failure.
+ */
+static void regress_framing(int rmode, FILE *fp, const char *what,
+ const void *p, size_t sz)
+{
+ if (regress_data(rmode, fp, what, p, sz))
+ die(1, "regression framing mismatch for %s (bug, or wrong file)", what);
+}
+
+/* Read or write crypto data from/to @fp@ according to @rmode@. The data
+ * item is describd as @what@ in diagnostic messages, and consists of the
+ * bytes beginning at @p@. For the purposes of diagnostics, this buffer has
+ * been notionally split into three pieces, with sizes @sz0@, @sz1@, and
+ * @sz2@, respectively.
+ *
+ * If al is well, return zero. If the crypto data doesn't match the recorded
+ * regression data, then report the mismatch, showing the way in which the
+ * buffer is split, and return -1. I/O errors are fatal.
+ */
+static int regress_crypto(int rmode, FILE *fp, const char *what, size_t blksz,
+ const void *p, size_t sz0, size_t sz1, size_t sz2)
+{
+ int rc;
+
+ rc = regress_data(rmode, fp, what, p, sz0 + sz1 + sz2);
+ if (rc) {
+ printf("\nRegression mismatch (split = %lu/%lu/%lu)\n",
+ (unsigned long)sz0, (unsigned long)sz1, (unsigned long)sz2);
+ dump_split("plaintext", blksz, text, sz0, sz1, sz2);
+ dump_split("expected ct", blksz, t, sz0, sz1, sz2);
+ dump_split("computed ct", blksz, p, sz0, sz1, sz2);
+ fputc('\n', stdout);
+ }
+ return (rc);
+}
+
+/*----- Selecting fragment sizes ------------------------------------------*/
+
+/* Return codes from @step@. */
+enum { STEP, LIMIT, RESET };
+
+/* Update @*sz_inout@ the next largest suitable fragment size, up to a
+ * maximum of @max@.
+ *
+ * If the new size is still smaller than the maximum, then return @STEP@. If
+ * the size is maximal, then return @LIMIT@. If the size was previously
+ * maximal already, then return @RESET@.
+ *
+ * The sizes here are selected powers of two, and powers of two plus or minus
+ * 1, with the objective of testing how internal buffering is affected when
+ * the cursor is misaligned and realigned with block boundaries.
+ */
+static int step(size_t *sz_inout, size_t max)
+{
+ size_t i;
+
+ static size_t steps[] = { 1, 7, 8, 9, 15, 16, 17,
+ 63, 64, 65, 255, 256, 257 };
+
+ if (*sz_inout == max) return (RESET);
+ for (i = 0; i < N(steps); i++)
+ if (steps[i] > *sz_inout) {
+ if (steps[i] < max) { *sz_inout = steps[i]; return (STEP); }
+ else break;
+ }
+ *sz_inout = max; return (LIMIT);
+}
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @test_encmode@ --- *
+ *
+ * Arguments: @const char *name@ = name of the encryption scheme; used to
+ * find the regression-test filename
+ * @size_t ksz@ = key size to use, or zero for `don't care'
+ * @size_t blksz@ = block size
+ * @size_t minsz@ = smallest acceptable buffer size, or 1
+ * @unsigned f@ = various additional flags
+ * @setupfn *setup@ = key-setup function
+ * @resetfn *reset@ = state-reset function
+ * @encfn *enc@ = encryption function
+ * @decfn *dec@ = decryption function
+ * @int argc@ = number of command-line arguments
+ * @char *argv@ = pointer to command-line argument vector
+ *
+ * Returns: Zero on success, nonzero to report failure.
+ *
+ * Use: Tests an encryption mode which doesn't have any more formal
+ * test vectors.
+ *
+ * The @name@ is used firstly in diagnostic output and secondly
+ * to form the default filename to use for regression-test data,
+ * as `.../symm/t/modes/NAME.regress'.
+ *
+ * The key size @ksz@ is simply passed on back to the @setup@
+ * function, unless the caller passes in zero, in which case
+ * @test_encmode@ chooses a key size for itself.
+ *
+ * The block size @blksz@ is used in failure reports, to draw
+ * attention to the block structure in the various buffers,
+ * which may assist with diagnosis. It's also used to determine
+ * when to apply a consistency check: see below regarding the
+ * @TEMF_REFALIGN@ flag.
+ *
+ * The minimum buffer size @minsz@ expresses a limitation on the
+ * provided @enc@ and @dec@ functions, that they don't work on
+ * inputs smaller than @minsz@; accordingly, @test_encmode@ will
+ * not test such small sizes. This should be 1 if the mode has
+ * no limitation.
+ *
+ * The flags @f@ influence testing in various ways explained
+ * below.
+ *
+ * The caller-provided functions are assumed to act on some
+ * global but hidden state,
+ *
+ * * @setup@ is (currently, at least) called only once, with
+ * the key @k@ and its chosen size @ksz@.
+ *
+ * * @reset@ is called at the start of each encryption or
+ * decryption operation, to program in the initialization
+ * vector to use. Currently, the same IV is used in all of
+ * the tests, but this might not always be the case.
+ *
+ * * @enc@ is called to encrypt a source buffer @s@ and write
+ * the ciphertext to a destination @d@; @sz@ is the common
+ * size of these buffers. @d@ might be null, to discard
+ * output; @s@ might be null, to process all-zero input.
+ *
+ * * @dec@ is called to decrypt a source buffer @s@ and write
+ * the recovered plaintext to a destination @d@; @sz@ is the
+ * common size of these buffers.
+ *
+ * Finally, @int argc@ and @char *argv@ are the command-line
+ * arguments provided to @main@; @test_encmode@ parses these and
+ * alters its behaviour accordingly.
+ *
+ * Currently, @test_encmode@'s tests are built around a single,
+ * fairly large, fixed message. In each test step, the message
+ * is split into a number of fragments which are encrypted and
+ * decrypted in turn.
+ *
+ * The following tests are performed.
+ *
+ * * The fundamental `round-trip' test, which verifies that
+ * the message can be encrypted and then decrypted
+ * successfully, if the same fragment boundaries are used in
+ * both cases.
+ *
+ * * A `consistency' test. Some modes, such as CFB, OFB, and
+ * counter, are `resumable': encryption operations are
+ * insensitive to the position of fragment boundaries, so a
+ * single message can be broken into fragments without
+ * affecting the result. If @TEMF_REFALIGN@ is clear then
+ * the mode under test is verified to have this property.
+ * If @TEMF_REFALIGN' is set, a weaker property is verified:
+ * that encryption is insensitive to the position of
+ * /block-aligned/ fragment boundaries only.
+ *
+ * * A `regression' test, which verifies that the code
+ * produces the same ciphertext as a previous version. By
+ * setting command-line arguments appropriately, a test
+ * program can be told to record ciphertexts in a (binary)
+ * data file. Usually, instead, the program will read the
+ * recorded ciphertexts back and verify that it produces the
+ * same data. For resumable modes, it's only necessary to
+ * record single ciphertext, since all the other ciphertexts
+ * must be equal by consistency; otherwise all non-block-
+ * aligned splits are recorded separately.
+ */
+
+int test_encmode(const char *name,
+ size_t ksz, size_t blksz, size_t minsz, unsigned f,
+ setupfn *setup, resetfn *reset, encfn *enc, encfn *dec,
+ int argc, char *argv[])
+{
+ int ok = 1, refp = 0, i;
+ size_t sz0, sz1, sz2;
+ const char spinner[] = "/-\\|";
+ int rmode = CHECK, spin = isatty(STDOUT_FILENO) ? 0 : -1;
+ int regr;
+ const char *rname = 0, *p;
+ FILE *fp;
+ dstr d = DSTR_INIT;
+
+ ego(argv[0]);
+
+ /* Parse the command-line options. */
+ p = 0; i = 1;
+ for (;;) {
+
+ /* Read the next argument. */
+ if (!p || !*p) {
+ if (i >= argc) break;
+ p = argv[i++];
+ if (strcmp(p, "--") == 0) break;
+ if (p[0] != '-' || p[1] == 0) { i--; break; }
+ p++;
+ }
+
+ /* Interpret an option. */
+ switch (*p++) {
+ case 'h':
+ printf("%s test driver\n"
+ "Usage: %s [-i] [-o|-f FILENAME]\n", QUIS, QUIS);
+ exit(0);
+ case 'i':
+ rmode = IGNORE;
+ break;
+ case 'o':
+ if (!*p) {
+ if (i >= argc) die(1, "option `-o' expects an argument");
+ p = argv[i++];
+ }
+ rmode = RECORD; rname = p; p = 0;
+ break;
+ case 'f':
+ if (!*p) {
+ if (i >= argc) die(1, "option `-f' expects an argument");
+ p = argv[i++];
+ }
+ rmode = CHECK; rname = p; p = 0;
+ break;
+ default:
+ die(1, "option `-%c' unknown", p[-1]);
+ }
+ }
+
+ /* Check there's nothing else left. */
+ if (i < argc) die(1, "trailing junk on command line");
+
+ /* Open the regression-data file. */
+ if (rmode == IGNORE)
+ fp = 0;
+ else {
+ if (!rname) {
+ DRESET(&d); dstr_putf(&d, SRCDIR"/t/modes/%s.regress", name);
+ rname = xstrdup(d.buf);
+ }
+ fp = fopen(rname, rmode == RECORD ? "wb" : "rb");
+ if (!fp)
+ die(1, "failed to open `%s' for %s: %s", rname,
+ rmode == RECORD ? "writing" : "reading", strerror(errno));
+ }
+
+ /* Write a header describing the file, to trap misuse for the wrong mode,
+ * and changes in the text.
+ */
+ DRESET(&d);
+ dstr_putf(&d, "mode=%s, text=%lu", name, (unsigned long)TEXTSZ);
+ regress_framing(rmode, fp, "header", d.buf, d.len);
+
+ /* Start things up. */
+ printf("%s: ", name);
+ setup(key, ksz ? ksz: sizeof(key));
+
+ /* Work through various sizes of up to three fragments. The middle
+ * fragment is the important one, since it can be misaligned or not at
+ * either end.
+ */
+ sz0 = sz1 = minsz;
+ for (;;) {
+
+ /* If output is to a terminal then display a spinner to keep humans
+ * amused.
+ */
+ if (spin >= 0) {
+ printf("\r%s: [%c]\b\b", name, spinner[spin]); fflush(stdout);
+ spin = (spin + 1)&3;
+ }
+
+ /* Prepare for the test. */
+ sz2 = TEXTSZ - sz1 - sz0;
+ ok = 1;
+
+ /* Encrypt the last fragment first, to check discarding behaviour. */
+ if (sz2) {
+ reset(iv);
+ enc(text, 0, sz0);
+ enc(text + sz0, 0, sz1);
+ enc(text + sz0 + sz1, ct + sz0 + sz1, sz2);
+ }
+
+ /* Encrypt the first two fragments. */
+ reset(iv);
+ enc(text, ct, sz0);
+ if (sz1) {
+ memcpy(ct + sz0, text + sz0, sz1);
+ enc(ct + sz0, ct + sz0, sz1);
+ }
+
+ /* Try to check consistency. We can't do this if (a) the mode is
+ * non-resumable and the fragments sizes are misaligned, or (b) this is
+ * our first pass through and we don't have a consistency reference yet.
+ *
+ * Also, decide whether to deploy the regression test, which we do if and
+ * only if we can't compare against the consistency reference.
+ */
+ regr = 0;
+ if ((f&TEMF_REFALIGN) && (sz0%blksz || sz1%blksz)) regr = 1;
+ else if (!refp) { memcpy(ref, ct, TEXTSZ); regr = 1; refp = 1; }
+ else if (memcmp(ref, ct, TEXTSZ) != 0) {
+ ok = 0;
+ printf("\nConsistency failure (split = %lu/%lu/%lu)\n",
+ (unsigned long)sz0, (unsigned long)sz1, (unsigned long)sz2);
+ dump_split("plaintext", blksz, text, sz0, sz1, sz2);
+ dump_split("reference", blksz, ref, sz0, sz1, sz2);
+ dump_split("ciphertext", blksz, ct, sz0, sz1, sz2);
+ fputc('\n', stdout);
+ }
+
+ /* If we need the regression test then do that. Write a framing record
+ * to avoid confusion if the policy changes.
+ */
+ if (regr) {
+ DRESET(&d);
+ dstr_putf(&d, "split = %lu/%lu/%lu",
+ (unsigned long)sz0, (unsigned long)sz1, (unsigned long)sz2);
+ regress_framing(rmode, fp, "split", d.buf, d.len);
+ if (regress_crypto(rmode, fp, "regress", blksz, ct, sz0, sz1, sz2))
+ ok = 0;
+ }
+
+ /* Finally, decrypt and check that the round-trip works. */
+ reset(iv);
+ dec(ct, pt, sz0);
+ if (sz1) {
+ memcpy(pt + sz0, ct + sz0, sz1);
+ dec(pt + sz0, pt + sz0, sz1);
+ }
+ if (sz2)
+ dec(ct + sz0 + sz1, pt + sz0 + sz1, sz2);
+ if (memcmp(text, pt, TEXTSZ) != 0) {
+ ok = 0;
+ printf("\nRound-trip failure (split = %lu/%lu/%lu)\n",
+ (unsigned long)sz0, (unsigned long)sz1, (unsigned long)sz2);
+ dump_split("plaintext", blksz, text, sz0, sz1, sz2);
+ dump_split("ciphertext", blksz, ct, sz0, sz1, sz2);
+ dump_split("recovered", blksz, pt, sz0, sz1, sz2);
+ fputc('\n', stdout);
+ }
+
+ /* Update the fragment sizes. */
+ if (!sz1) break;
+ if (step(&sz1, TEXTSZ - sz0) == RESET) {
+ if (step(&sz0, TEXTSZ) == LIMIT) sz1 = 0;
+ else sz1 = minsz;
+ }
+ }
+
+ /* Close the regression data file. */
+ if (fp && (ferror(fp) || fclose(fp)))
+ die(1, "error closing `%s': %s", rname, strerror(errno));
+
+ /* Finish off the eyecandy spinner. */
+ if (spin >= 0) printf("\r%s: [%c] ", name, ok ? '*' : 'X');
+
+ /* Summarize the test result. */
+ if (ok) printf("ok\n");
+ else printf("failed\n");
+
+ /* And we're done. */
+ dstr_destroy(&d);
+ return (!ok);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
--- /dev/null
+/* -*-c-*-
+ *
+ * Common testing for encryption modes
+ *
+ * (c) 2018 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef CATACOMB_MODES_TEST_H
+#define CATACOMB_MODES_TEST_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+/*----- Data structures ---------------------------------------------------*/
+
+/* Functions used by `test_encmode' below. */
+typedef void setupfn(const octet */*k*/, size_t /*ksz*/);
+typedef void resetfn(const octet */*iv*/);
+typedef void encfn(const octet */*s*/, octet */*d*/, size_t /*sz*/);
+
+/*----- Functions provided ------------------------------------------------*/
+
+#define TEMF_REFALIGN 1u /* misalignment of pieces affects
+ * the encryption state
+ */
+
+/* --- @test_encmode@ --- *
+ *
+ * Arguments: @const char *name@ = name of the encryption scheme; used to
+ * find the regression-test filename
+ * @size_t ksz@ = key size to use, or zero for `don't care'
+ * @size_t blksz@ = block size
+ * @size_t minsz@ = smallest acceptable buffer size, or 1
+ * @unsigned f@ = various additional flags
+ * @setupfn *setup@ = key-setup function
+ * @resetfn *reset@ = state-reset function
+ * @encfn *enc@ = encryption function
+ * @decfn *dec@ = decryption function
+ * @int argc@ = number of command-line arguments
+ * @char *argv@ = pointer to command-line argument vector
+ *
+ * Returns: Zero on success, nonzero to report failure.
+ *
+ * Use: Tests an encryption mode which doesn't have any more formal
+ * test vectors.
+ *
+ * The @name@ is used firstly in diagnostic output and secondly
+ * to form the default filename to use for regression-test data,
+ * as `.../symm/t/modes/NAME.regress'.
+ *
+ * The key size @ksz@ is simply passed on back to the @setup@
+ * function, unless the caller passes in zero, in which case
+ * @test_encmode@ chooses a key size for itself.
+ *
+ * The block size @blksz@ is used in failure reports, to draw
+ * attention to the block structure in the various buffers,
+ * which may assist with diagnosis. It's also used to determine
+ * when to apply a consistency check: see below regarding the
+ * @TEMF_REFALIGN@ flag.
+ *
+ * The minimum buffer size @minsz@ expresses a limitation on the
+ * provided @enc@ and @dec@ functions, that they don't work on
+ * inputs smaller than @minsz@; accordingly, @test_encmode@ will
+ * not test such small sizes. This should be 1 if the mode has
+ * no limitation.
+ *
+ * The flags @f@ influence testing in various ways explained
+ * below.
+ *
+ * The caller-provided functions are assumed to act on some
+ * global but hidden state,
+ *
+ * * @setup@ is (currently, at least) called only once, with
+ * the key @k@ and its chosen size @ksz@.
+ *
+ * * @reset@ is called at the start of each encryption or
+ * decryption operation, to program in the initialization
+ * vector to use. Currently, the same IV is used in all of
+ * the tests, but this might not always be the case.
+ *
+ * * @enc@ is called to encrypt a source buffer @s@ and write
+ * the ciphertext to a destination @d@; @sz@ is the common
+ * size of these buffers. @d@ might be null, to discard
+ * output; @s@ might be null, to process all-zero input.
+ *
+ * * @dec@ is called to decrypt a source buffer @s@ and write
+ * the recovered plaintext to a destination @d@; @sz@ is the
+ * common size of these buffers.
+ *
+ * Finally, @int argc@ and @char *argv@ are the command-line
+ * arguments provided to @main@; @test_encmode@ parses these and
+ * alters its behaviour accordingly.
+ *
+ * Currently, @test_encmode@'s tests are built around a single,
+ * fairly large, fixed message. In each test step, the message
+ * is split into a number of fragments which are encrypted and
+ * decrypted in turn.
+ *
+ * The following tests are performed.
+ *
+ * * The fundamental `round-trip' test, which verifies that
+ * the message can be encrypted and then decrypted
+ * successfully, if the same fragment boundaries are used in
+ * both cases.
+ *
+ * * A `consistency' test. Some modes, such as CFB, OFB, and
+ * counter, are `resumable': encryption operations are
+ * insensitive to the position of fragment boundaries, so a
+ * single message can be broken into fragments without
+ * affecting the result. If @TEMF_REFALIGN@ is clear then
+ * the mode under test is verified to have this property.
+ * If @TEMF_REFALIGN' is set, a weaker property is verified:
+ * that encryption is insensitive to the position of
+ * /block-aligned/ fragment boundaries only.
+ *
+ * * A `regression' test, which verifies that the code
+ * produces the same ciphertext as a previous version. By
+ * setting command-line arguments appropriately, a test
+ * program can be told to record ciphertexts in a (binary)
+ * data file. Usually, instead, the program will read the
+ * recorded ciphertexts back and verify that it produces the
+ * same data. For resumable modes, it's only necessary to
+ * record single ciphertext, since all the other ciphertexts
+ * must be equal by consistency; otherwise all non-block-
+ * aligned splits are recorded separately.
+ */
+
+extern int test_encmode(const char */*name*/,
+ size_t /*ksz*/, size_t /*blksz*/,
+ size_t /*minsz */, unsigned /*f*/,
+ setupfn */*setup*/, resetfn */*reset*/,
+ encfn */*enc*/, encfn */*dec*/,
+ int /*argc*/, char */*argv*/[]);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
CIPHER_MODES += @{hash:f}-@hashciphermode
%end
+## Modes for authenticated encryption.
+AEAD_MODES =
+%repeat
+AEAD_MODES += @{blkc:f}-@blkcaeadmode
+%end
+
## Modes for message authentication.
MAC_MODES =
%repeat
+MAC_MODES += @{blkc:f}-@blkcmacmode
+%end
+%repeat
MAC_MODES += @{hash:f}-@hashmacmode
%end
%repeat
SYMM_TEST_FILES += t/@{hash:f}
%end
+
+## Regression-test files.
+REGRESSION_TEST_FILES =
+%repeat
+REGRESSION_TEST_FILES += t/modes/@{blkc:f}-@{blkcciphermode}.regress
+%end
+%repeat
+REGRESSION_TEST_FILES += t/modes/@{hash:f}-@{hashciphermode}.regress
+%end
--- /dev/null
+/* -*-c-*-
+ *
+ * Common definitions for OCB and related modes
+ *
+ * (c) 2018 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "config.h"
+
+#include "ocb.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+/* --- @ocb_ctz@, @ocb_ctzl@ --- *
+ *
+ * Arguments: @unsigned i@ or @unsigned long i@ = operand, assumed nonzero
+ *
+ * Returns: The number of trailing zero bits in @i@, or nonsense if
+ * %$i = 0$%.
+ */
+
+unsigned ocb_ctz(unsigned i)
+{
+ unsigned n = 0;
+
+ if (!(i&0x00ff)) { n += 8; i >>= 8; }
+ if (!(i&0x000f)) { n += 4; i >>= 4; }
+ if (!(i&0x0003)) { n += 2; i >>= 2; }
+ if (!(i&0x0001)) { n += 1; i >>= 1; }
+ return (n);
+}
+
+unsigned ocb_ctzl(unsigned long i)
+{
+ unsigned n = 0;
+
+#if ULONG_BITS > 64
+ while (!(i&0xfffffffffffffffful)) { n += 64; i >>= 64; }
+#endif
+#if ULONG_BITS > 32
+ if (!(i&0xffffffff)) { n += 32; i >>= 32; }
+#endif
+ if (!(i&0xffff)) { n += 16; i >>= 16; }
+ if (!(i&0x00ff)) { n += 8; i >>= 8; }
+ if (!(i&0x000f)) { n += 4; i >>= 4; }
+ if (!(i&0x0003)) { n += 2; i >>= 2; }
+ if (!(i&0x0001)) { n += 1; i >>= 1; }
+ return (n);
+}
+
+/*----- That's all, folks -------------------------------------------------*/
--- /dev/null
+/* -*-c-*-
+ *
+ * Common definitions for OCB and related modes
+ *
+ * (c) 2018 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef CATACOMB_OCB_H
+#define CATACOMB_OCB_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+#include <mLib/compiler.h>
+
+/*----- Constants ---------------------------------------------------------*/
+
+/* The number of offsets to maintain. Rather than calculate and store all
+ * possible offset values in advance, or calculate new ones on demand (and
+ * have to allocate space for them), we calculate a number in advance, and
+ * determine any others every time they're needed. If we calculate the first
+ * %$n$% offsets only, then we spend %$i - n + 1$% time calculating offset
+ * %$L_i$% when %$i \ge n$%. But the offset %$L_i$% is used only for a
+ * %$2^{-i-1}$% fraction of the blocks. Summing up this geometric series
+ * shows us that we add only a small constant overhead, and save storage
+ * space for many offsets.
+ */
+#define OCB_NCALC 16
+#define OCB_CALCMASK ((1ul << OCB_NCALC) - 1)
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @ocb_ctz@, @ocb_ctzl@ --- *
+ *
+ * Arguments: @unsigned i@ or @unsigned long i@ = operand, assumed nonzero
+ *
+ * Returns: The number of trailing zero bits in @i@, or nonsense if
+ * %$i = 0$%.
+ */
+
+extern unsigned ocb_ctz(unsigned /*i*/);
+extern unsigned ocb_ctzl(unsigned long /*i*/);
+
+#if GCC_VERSION_P(3, 4)
+# define OCB_CTZ(i) __builtin_ctz(i)
+# define OCB_CTZL(i) __builtin_ctzl(i)
+#else
+# define OCB_CTZ(i) ocb_ctz(i)
+# define OCB_CTZL(i) ocb_ctzl(i)
+#endif
+
+/* --- @OCB_OFFSET@ --- *
+ *
+ * Arguments: @PRE@ = block cipher prefix
+ * @uint32 *o@ = pointer to offset accumulator
+ * @uint32 (*l)[PRE_BLKSZ]@ = pointer to offset mask table
+ * @unsigned long i@ = block index
+ *
+ * Returns: ---
+ *
+ * Use: Update the per-block offset for Grey-code-based OCB
+ * variants. On entry, @o@ is assumed to hold the offset for
+ * block @i - 1@; on exit @o@ is updated to hold the offset for
+ * block @i@.
+ */
+
+#define OCB_OFFSET(PRE, o, l, i) do { \
+ uint32 (*_l)[PRE##_BLKSZ/4] = (l); \
+ uint32 *_o = (o); \
+ unsigned long _i = (i); \
+ unsigned _j; \
+ \
+ if (_i&OCB_CALCMASK) { \
+ _j = OCB_CTZ(_i); \
+ BLKC_XMOVE(PRE, _o, _l[_j]); \
+ } else { \
+ uint32 _t[PRE##_BLKSZ]; \
+ _j = OCB_CTZL(_i) - OCB_NCALC; \
+ BLKC_BLSHIFT(PRE, IRRED, _t, _l[OCB_NCALC - 1]); \
+ while (_j--) BLKC_BLSHIFT(PRE, IRRED, _t, _t); \
+ BLKC_XMOVE(PRE, _t, _l[_j]); \
+ } \
+} while (0)
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
--- /dev/null
+/* -*-c-*-
+ *
+ * The OCB1 authenticated encryption mode
+ *
+ * (c) 2018 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef CATACOMB_OCB1_DEF_H
+#define CATACOMB_OCB1_DEF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#ifndef CATACOMB_ARENA_H
+# include "arena.h"
+#endif
+
+#ifndef CATACOMB_BLKC_H
+# include "blkc.h"
+#endif
+
+#ifndef CATACOMB_CT_H
+# include "ct.h"
+#endif
+
+#ifndef CATACOMB_KEYSZ_H
+# include "keysz.h"
+#endif
+
+#ifndef CATACOMB_PARANOIA_H
+# include "paranoia.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @OCB1_DEF@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Creates an implementation for the OCB1 authenticated-
+ * encryption mode.
+ */
+
+#define OCB1_DEF(PRE, pre) OCB1_DEFX(PRE, pre, #pre, #pre)
+
+#define OCB1_DEFX(PRE, pre, name, fname) \
+ \
+const octet \
+ pre##_ocb1noncesz[] = { KSZ_SET, PRE##_BLKSZ, 0 }, \
+ pre##_ocb1tagsz[] = { KSZ_RANGE, PRE##_BLKSZ, 0, PRE##_BLKSZ, 1 }; \
+ \
+/* --- @pre_ocb1init@ --- * \
+ * \
+ * Arguments: @pre_ocb1ctx *ctx@ = pointer to OCB1 context \
+ * @const pre_ocb1key *key@ = pointer to key block \
+ * @const void *n@ = pointer to nonce \
+ * @size_t nsz@ = size of nonce \
+ * \
+ * Returns: Zero on success, @-1@ if the nonce length is bad. \
+ * \
+ * Use: Initialize an OCB1 operation context with a given key. \
+ * \
+ * The original key needn't be kept around any more. \
+ */ \
+ \
+int pre##_ocb1init(pre##_ocb1ctx *ctx, const pre##_ocb1key *k, \
+ const void *n, size_t nsz) \
+ { ctx->k = *k; return (pre##_ocb1reinit(ctx, n, nsz)); } \
+ \
+/* --- @pre_ocb1reinit@ --- * \
+ * \
+ * Arguments: @pre_ocb1ctx *ctx@ = pointer to OCB1 context \
+ * @const void *n@ = pointer to nonce \
+ * @size_t nsz@ = size of nonce \
+ * \
+ * Returns: Zero on success, @-1@ if the nonce length is bad. \
+ * \
+ * Use: Reinitialize an OCB1 operation context, changing the \
+ * nonce. \
+ */ \
+ \
+int pre##_ocb1reinit(pre##_ocb1ctx *ctx, const void *n, size_t nsz) \
+{ \
+ if (nsz != PRE##_BLKSZ) return (-1); \
+ ctx->off = 0; BLKC_ZERO(PRE, ctx->a); \
+ BLKC_LOAD(PRE, ctx->o, n); BLKC_XMOVE(PRE, ctx->o, ctx->k.lmask[0]); \
+ pre##_eblk(&ctx->k.ctx, ctx->o, ctx->o); ctx->i = 1; \
+ return (0); \
+} \
+ \
+/* --- @pre_ocb1encrypt@ --- * \
+ * \
+ * Arguments: @pre_ocb1ctx *ctx@ = pointer to OCB1 operation context \
+ * @const void *src@ = pointer to plaintext message chunk \
+ * @size_t sz@ = size of the plaintext \
+ * @buf *dst@ = a buffer to write the ciphertext to \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Encrypts a chunk of a plaintext message, writing a \
+ * chunk of ciphertext to the output buffer and updating \
+ * the operation state. \
+ * \
+ * Note that OCB1 delays output if its input is not a \
+ * whole number of blocks. This means that the output \
+ * might be smaller or larger the input by up to the block \
+ * size. \
+ */ \
+ \
+int pre##_ocb1encrypt(pre##_ocb1ctx *ctx, \
+ const void *src, size_t sz, buf *dst) \
+{ \
+ rsvr_state st; \
+ size_t osz; \
+ uint32 t[PRE##_BLKSZ/4]; \
+ const octet *p; \
+ octet *q; \
+ \
+ /* Figure out what we're going to do. */ \
+ rsvr_setup(&st, &pre##_ocb1policy, ctx->b, &ctx->off, src, sz); \
+ \
+ /* Determine the output size and verify that there is enough \
+ * space. \
+ */ \
+ osz = st.plan.from_rsvr + st.plan.from_input; \
+ if (!osz) q = 0; \
+ else { q = buf_get(dst, osz); if (!q) return (-1); } \
+ \
+ /* Process the input in whole blocks at a time. */ \
+ RSVR_DO(&st) while ((p = RSVR_NEXT(&st, PRE##_BLKSZ)) != 0) { \
+ OCB_OFFSET(PRE, ctx->o, ctx->k.lmask, ctx->i++); \
+ BLKC_LOAD(PRE, t, p); BLKC_XMOVE(PRE, ctx->a, t); \
+ BLKC_XMOVE(PRE, t, ctx->o); pre##_eblk(&ctx->k.ctx, t, t); \
+ BLKC_XSTORE(PRE, q, t, ctx->o); q += PRE##_BLKSZ; \
+ } \
+ \
+ /* Done. */ \
+ return (0); \
+} \
+ \
+/* --- @pre_ocb1decrypt@ --- * \
+ * \
+ * Arguments: @pre_ocb1ctx *ctx@ = pointer to OCB1 operation context \
+ * @const void *src@ = pointer to ciphertext message chunk \
+ * @size_t sz@ = size of the ciphertext \
+ * @buf *dst@ = a buffer to write the plaintext to \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Decrypts a chunk of a ciphertext message, writing a \
+ * chunk of plaintext to the output buffer and updating \
+ * the operation state. \
+ * \
+ * Note that OCB1 delays output if its input is not a \
+ * whole number of blocks. This means that the output \
+ * might be smaller or larger the input by up to the block \
+ * size. \
+ */ \
+ \
+int pre##_ocb1decrypt(pre##_ocb1ctx *ctx, \
+ const void *src, size_t sz, buf *dst) \
+{ \
+ rsvr_state st; \
+ size_t osz; \
+ uint32 t[PRE##_BLKSZ/4]; \
+ const octet *p; \
+ octet *q; \
+ \
+ /* Figure out what we're going to do. */ \
+ rsvr_setup(&st, &pre##_ocb1policy, ctx->b, &ctx->off, src, sz); \
+ \
+ /* Determine the output size and verify that there is enough \
+ * space. \
+ */ \
+ osz = st.plan.from_rsvr + st.plan.from_input; \
+ if (!osz) q = 0; \
+ else { q = buf_get(dst, osz); if (!q) return (-1); } \
+ \
+ /* Process the input in whole blocks at a time. */ \
+ RSVR_DO(&st) while ((p = RSVR_NEXT(&st, PRE##_BLKSZ)) != 0) { \
+ OCB_OFFSET(PRE, ctx->o, ctx->k.lmask, ctx->i++); \
+ BLKC_LOAD(PRE, t, p); \
+ BLKC_XMOVE(PRE, t, ctx->o); pre##_dblk(&ctx->k.ctx, t, t); \
+ BLKC_XMOVE(PRE, t, ctx->o); BLKC_XMOVE(PRE, ctx->a, t); \
+ BLKC_STORE(PRE, q, t); q += PRE##_BLKSZ; \
+ } \
+ \
+ /* Done. */ \
+ return (0); \
+} \
+ \
+/* --- @pre_ocb1encdecfinal@ --- * \
+ * \
+ * Arguments: @pre_ocb1ctx *ctx@ = pointer to an OCB1 context \
+ * @const pre_ocb1aadctx *aad@ = pointer to AAD context, \
+ * or null \
+ * @buf *dst@ = buffer for remaining ciphertext \
+ * @int encp@ = nonzero if we're encrypting \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Common end-of-message handling for encryption and \
+ * decryption. The full-length tag is left in the \
+ * context's buffer. \
+ */ \
+ \
+static int pre##_ocb1encdecfinal(pre##_ocb1ctx *ctx, \
+ const pre##_ocb1aadctx *aad, buf *dst, \
+ int encp) \
+{ \
+ octet *q; \
+ \
+ /* Arrange space for the final output (if any). */ \
+ if (!ctx->off) { q = 0; if (!BOK(dst)) return (-1); } \
+ else { q = buf_get(dst, ctx->off); if (!q) return (-1); } \
+ \
+ /* Calculate the final offset. Mix it into the checksum before it \
+ * gets clobbered. \
+ */ \
+ OCB_OFFSET(PRE, ctx->o, ctx->k.lmask, ctx->i++); \
+ BLKC_XMOVE(PRE, ctx->a, ctx->o); \
+ \
+ /* Mix the magic final mask and tail length into the offset. */ \
+ BLKC_XMOVE(PRE, ctx->o, ctx->k.lxinv); \
+ ctx->o[PRE##_BLKSZ/4 - 1] ^= BLKC_BWORD(PRE, 8*ctx->off); \
+ \
+ /* If we're decrypting, then trim the end of the plaintext and fold \
+ * that into the checksum. \
+ */ \
+ if (!encp) { \
+ memset(ctx->b + ctx->off, 0, PRE##_BLKSZ - ctx->off); \
+ BLKC_XLOAD(PRE, ctx->a, ctx->b); \
+ } \
+ \
+ /* Cycle the block cipher for the last plaintext block. */ \
+ pre##_eblk(&ctx->k.ctx, ctx->o, ctx->o); \
+ \
+ /* Fold this mask into the checksum before it gets clobbered. */ \
+ BLKC_XMOVE(PRE, ctx->a, ctx->o); \
+ \
+ /* Encrypt the message tail. */ \
+ BLKC_XLOAD(PRE, ctx->o, ctx->b); \
+ BLKC_STORE(PRE, ctx->b, ctx->o); \
+ if (ctx->off) memcpy(q, ctx->b, ctx->off); \
+ \
+ /* If we're encrypting, then trim the end of the ciphertext and fold \
+ * that into the checksum. \
+ */ \
+ if (encp) { \
+ memset(ctx->b + ctx->off, 0, PRE##_BLKSZ - ctx->off); \
+ BLKC_XLOAD(PRE, ctx->a, ctx->b); \
+ } \
+ \
+ /* Encrypt the checksum to produce a tag. */ \
+ pre##_eblk(&ctx->k.ctx, ctx->a, ctx->a); \
+ \
+ /* If there's AAD then mix the PMAC tag in too. */ \
+ if (aad && aad->off) \
+ { pre##_ocb1aadtag(aad, ctx->o); BLKC_XMOVE(PRE, ctx->a, ctx->o); } \
+ \
+ /* Write the final tag. */ \
+ BLKC_STORE(PRE, ctx->b, ctx->a); \
+ \
+ /* Done. */ \
+ return (0); \
+} \
+ \
+/* --- @pre_ocb1encryptdone@ --- * \
+ * \
+ * Arguments: @pre_ocb1ctx *ctx@ = pointer to an OCB1 context \
+ * @const pre_ocb1aadctx *aad@ = pointer to AAD context, \
+ * or null \
+ * @buf *dst@ = buffer for remaining ciphertext \
+ * @void *tag@ = where to write the tag \
+ * @size_t tsz@ = length of tag to store \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Completes an OCB1 encryption operation. The @aad@ \
+ * pointer may be null if there is no additional \
+ * authenticated data. OCB1 delays output, so this will \
+ * cause any remaining buffered plaintext to be encrypted \
+ * and written to @dst@. Anyway, the function will fail \
+ * if the output buffer is broken. \
+ */ \
+ \
+int pre##_ocb1encryptdone(pre##_ocb1ctx *ctx, \
+ const pre##_ocb1aadctx *aad, buf *dst, \
+ void *tag, size_t tsz) \
+{ \
+ assert(tsz <= PRE##_BLKSZ); \
+ if (pre##_ocb1encdecfinal(ctx, aad, dst, 1)) return (-1); \
+ memcpy(tag, ctx->b, tsz); \
+ return (0); \
+} \
+ \
+/* --- @pre_ocb1decryptdone@ --- * \
+ * \
+ * Arguments: @pre_ocb1ctx *ctx@ = pointer to an OCB1 context \
+ * @const pre_ocb1aadctx *aad@ = pointer to AAD context, \
+ * or null \
+ * @buf *dst@ = buffer for remaining plaintext \
+ * @const void *tag@ = tag to verify \
+ * @size_t tsz@ = length of tag \
+ * \
+ * Returns: @+1@ for complete success; @0@ if tag verification \
+ * failed; @-1@ for other kinds of errors. \
+ * \
+ * Use: Completes an OCB1 decryption operation. The @aad@ \
+ * pointer may be null if there is no additional \
+ * authenticated data. OCB1 delays output, so this will \
+ * cause any remaining buffered ciphertext to be decrypted \
+ * and written to @dst@. Anyway, the function will fail \
+ * if the output buffer is broken. \
+ */ \
+ \
+int pre##_ocb1decryptdone(pre##_ocb1ctx *ctx, \
+ const pre##_ocb1aadctx *aad, buf *dst, \
+ const void *tag, size_t tsz) \
+{ \
+ assert(tsz <= PRE##_BLKSZ); \
+ if (pre##_ocb1encdecfinal(ctx, aad, dst, 0)) return (-1); \
+ else if (ct_memeq(tag, ctx->b, tsz)) return (+1); \
+ else return (0); \
+} \
+ \
+/* --- Generic AEAD interface --- */ \
+ \
+typedef struct gactx { \
+ gaead_aad a; \
+ pre##_ocb1aadctx aad; \
+} gactx; \
+ \
+static gaead_aad *gadup(const gaead_aad *a) \
+ { gactx *aad = S_CREATE(gactx); *aad = *(gactx *)a; return (&aad->a); } \
+ \
+static void gahash(gaead_aad *a, const void *h, size_t hsz) \
+ { gactx *aad = (gactx *)a; pre##_ocb1aadhash(&aad->aad, h, hsz); } \
+ \
+static void gadestroy(gaead_aad *a) \
+ { gactx *aad = (gactx *)a; BURN(*aad); S_DESTROY(aad); } \
+ \
+static const gaead_aadops gaops = \
+ { &pre##_ocb1, gadup, gahash, gadestroy }; \
+ \
+static gaead_aad *gaad(const pre##_ocb1key *k) \
+{ \
+ gactx *aad = S_CREATE(gactx); \
+ aad->a.ops = &gaops; \
+ pre##_ocb1aadinit(&aad->aad, k); \
+ return (&aad->a); \
+} \
+ \
+typedef struct gectx { \
+ gaead_enc e; \
+ pre##_ocb1ctx ctx; \
+} gectx; \
+ \
+static gaead_aad *geaad(gaead_enc *e) \
+ { gectx *enc = (gectx *)e; return (gaad(&enc->ctx.k)); } \
+ \
+static int gereinit(gaead_enc *e, const void *n, size_t nsz, \
+ size_t hsz, size_t msz, size_t tsz) \
+{ \
+ gectx *enc = (gectx *)e; \
+ return (pre##_ocb1reinit(&enc->ctx, n, nsz)); \
+} \
+ \
+static int geenc(gaead_enc *e, const void *m, size_t msz, buf *b) \
+{ \
+ gectx *enc = (gectx *)e; \
+ return (pre##_ocb1encrypt(&enc->ctx, m, msz, b)); \
+} \
+ \
+static int gedone(gaead_enc *e, const gaead_aad *a, \
+ buf *b, void *t, size_t tsz) \
+{ \
+ gectx *enc = (gectx *)e; gactx *aad = (gactx *)a; \
+ assert(!a || a->ops == &gaops); \
+ return (pre##_ocb1encryptdone(&enc->ctx, a ? &aad->aad : 0, b, t, tsz)); \
+} \
+ \
+static void gedestroy(gaead_enc *e) \
+ { gectx *enc = (gectx *)e; BURN(*enc); S_DESTROY(enc); } \
+ \
+static const gaead_encops geops = \
+ { &pre##_ocb1, geaad, gereinit, geenc, gedone, gedestroy }; \
+ \
+typedef struct gdctx { \
+ gaead_dec d; \
+ pre##_ocb1ctx ctx; \
+} gdctx; \
+ \
+static gaead_aad *gdaad(gaead_dec *d) \
+ { gdctx *dec = (gdctx *)d; return (gaad(&dec->ctx.k)); } \
+ \
+static int gdreinit(gaead_dec *d, const void *n, size_t nsz, \
+ size_t hsz, size_t csz, size_t tsz) \
+{ \
+ gdctx *dec = (gdctx *)d; \
+ return (pre##_ocb1reinit(&dec->ctx, n, nsz)); \
+} \
+ \
+static int gddec(gaead_dec *d, const void *c, size_t csz, buf *b) \
+{ \
+ gdctx *dec = (gdctx *)d; \
+ return (pre##_ocb1decrypt(&dec->ctx, c, csz, b)); \
+} \
+ \
+static int gddone(gaead_dec *d, const gaead_aad *a, \
+ buf *b, const void *t, size_t tsz) \
+{ \
+ gdctx *dec = (gdctx *)d; gactx *aad = (gactx *)a; \
+ assert(!a || a->ops == &gaops); \
+ return (pre##_ocb1decryptdone(&dec->ctx, a ? &aad->aad : 0, b, t, tsz)); \
+} \
+ \
+static void gddestroy(gaead_dec *d) \
+ { gdctx *dec = (gdctx *)d; BURN(*dec); S_DESTROY(dec); } \
+ \
+static const gaead_decops gdops = \
+ { &pre##_ocb1, gdaad, gdreinit, gddec, gddone, gddestroy }; \
+ \
+typedef struct gkctx { \
+ gaead_key k; \
+ pre##_ocb1key key; \
+} gkctx; \
+ \
+static gaead_aad *gkaad(const gaead_key *k) \
+ { gkctx *key = (gkctx *)k; return (gaad(&key->key)); } \
+ \
+static gaead_enc *gkenc(const gaead_key *k, const void *n, size_t nsz, \
+ size_t hsz, size_t msz, size_t tsz) \
+{ \
+ gkctx *key = (gkctx *)k; \
+ gectx *enc = S_CREATE(gectx); \
+ \
+ enc->e.ops = &geops; \
+ if (pre##_ocb1init(&enc->ctx, &key->key, n, nsz)) \
+ { gedestroy(&enc->e); return (0); } \
+ return (&enc->e); \
+} \
+ \
+static gaead_dec *gkdec(const gaead_key *k, const void *n, size_t nsz, \
+ size_t hsz, size_t csz, size_t tsz) \
+{ \
+ gkctx *key = (gkctx *)k; \
+ gdctx *dec = S_CREATE(gdctx); \
+ \
+ dec->d.ops = &gdops; \
+ if (pre##_ocb1init(&dec->ctx, &key->key, n, nsz)) \
+ { gddestroy(&dec->d); return (0); } \
+ return (&dec->d); \
+} \
+ \
+static void gkdestroy(gaead_key *k) \
+ { gkctx *key = (gkctx *)k; BURN(*key); S_DESTROY(key); } \
+ \
+static const gaead_keyops gkops = \
+ { &pre##_ocb1, gkaad, gkenc, gkdec, gkdestroy }; \
+ \
+static gaead_key *gckey(const void *k, size_t ksz) \
+{ \
+ gkctx *key = S_CREATE(gkctx); \
+ key->k.ops = &gkops; \
+ pre##_ocb1setkey(&key->key, k, ksz); \
+ return (&key->k); \
+} \
+ \
+const gcaead pre##_ocb1 = { \
+ name "-ocb1", \
+ pre##_keysz, pre##_ocb1noncesz, pre##_ocb1tagsz, \
+ PRE##_BLKSZ, PRE##_BLKSZ, 0, 0, \
+ gckey \
+}; \
+ \
+OCB1_TESTX(PRE, pre, name, fname)
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#define OCB1_TEST(PRE, pre) OCB1_TESTX(PRE, pre, #pre, #pre)
+
+/* --- @OCB1_TEST@ --- *
+ *
+ * Arguments: @PRE, pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Standard test rig for OCB1 functions.
+ */
+
+#ifdef TEST_RIG
+
+#include <stdio.h>
+
+#include <mLib/dstr.h>
+#include <mLib/quis.h>
+#include <mLib/testrig.h>
+
+#define OCB1_TESTX(PRE, pre, name, fname) \
+ \
+static int ocb1verify(dstr *v) \
+{ \
+ pre##_ocb1key key; \
+ pre##_ocb1aadctx aad; \
+ pre##_ocb1ctx ctx; \
+ int ok = 1, win; \
+ int i; \
+ octet *p; \
+ int szs[] = { 1, 7, 192, -1, 0 }, *ip; \
+ size_t hsz, msz; \
+ dstr d = DSTR_INIT, t = DSTR_INIT; \
+ buf b; \
+ \
+ dstr_ensure(&d, v[4].len > v[3].len ? v[4].len : v[3].len); \
+ dstr_ensure(&t, v[5].len); t.len = v[5].len; \
+ \
+ pre##_ocb1setkey(&key, v[0].buf, v[0].len); \
+ \
+ for (ip = szs; *ip; ip++) { \
+ \
+ pre##_ocb1init(&ctx, &key, (octet *)v[1].buf, v[1].len); \
+ \
+ i = *ip; \
+ hsz = v[2].len; \
+ if (i == -1) i = hsz; \
+ if (i > hsz) continue; \
+ p = (octet *)v[2].buf; \
+ pre##_ocb1aadinit(&aad, &key); \
+ while (hsz) { \
+ if (i > hsz) i = hsz; \
+ pre##_ocb1aadhash(&aad, p, i); \
+ p += i; hsz -= i; \
+ } \
+ \
+ buf_init(&b, d.buf, d.sz); \
+ i = *ip; \
+ msz = v[3].len; \
+ if (i == -1) i = msz; \
+ if (i > msz) continue; \
+ p = (octet *)v[3].buf; \
+ while (msz) { \
+ if (i > msz) i = msz; \
+ if (pre##_ocb1encrypt(&ctx, p, i, &b)) { \
+ puts("!! ocb1encrypt reports failure"); \
+ goto fail_enc; \
+ } \
+ p += i; msz -= i; \
+ } \
+ \
+ if (pre##_ocb1encryptdone(&ctx, &aad, &b, (octet *)t.buf, t.len)) { \
+ puts("!! ocb1encryptdone reports failure"); \
+ goto fail_enc; \
+ } \
+ d.len = BLEN(&b); \
+ \
+ if (d.len != v[4].len || \
+ memcmp(d.buf, v[4].buf, v[4].len) != 0 || \
+ memcmp(t.buf, v[5].buf, v[5].len) != 0) { \
+ fail_enc: \
+ printf("\nfail encrypt:\n\tstep = %i", *ip); \
+ fputs("\n\tkey = ", stdout); type_hex.dump(&v[0], stdout); \
+ fputs("\n\tnonce = ", stdout); type_hex.dump(&v[1], stdout); \
+ fputs("\n\theader = ", stdout); type_hex.dump(&v[2], stdout); \
+ fputs("\n\tmessage = ", stdout); type_hex.dump(&v[3], stdout); \
+ fputs("\n\texp ct = ", stdout); type_hex.dump(&v[4], stdout); \
+ fputs("\n\tcalc ct = ", stdout); type_hex.dump(&d, stdout); \
+ fputs("\n\texp tag = ", stdout); type_hex.dump(&v[5], stdout); \
+ fputs("\n\tcalc tag = ", stdout); type_hex.dump(&t, stdout); \
+ putchar('\n'); \
+ ok = 0; \
+ } \
+ \
+ pre##_ocb1init(&ctx, &key, (octet *)v[1].buf, v[1].len); \
+ \
+ buf_init(&b, d.buf, d.sz); \
+ i = *ip; \
+ msz = v[4].len; \
+ if (i == -1) i = msz; \
+ if (i > msz) continue; \
+ p = (octet *)v[4].buf; \
+ while (msz) { \
+ if (i > msz) i = msz; \
+ if (pre##_ocb1decrypt(&ctx, p, i, &b)) { \
+ puts("!! ocb1decrypt reports failure"); \
+ win = 0; goto fail_dec; \
+ } \
+ p += i; msz -= i; \
+ } \
+ \
+ win = pre##_ocb1decryptdone(&ctx, &aad, &b, \
+ (octet *)v[5].buf, v[5].len); \
+ if (win < 0) { \
+ puts("!! ocb1decryptdone reports failure"); \
+ goto fail_dec; \
+ } \
+ d.len = BLEN(&b); \
+ \
+ if (d.len != v[3].len || !win || \
+ memcmp(d.buf, v[3].buf, v[3].len) != 0) { \
+ fail_dec: \
+ printf("\nfail decrypt:\n\tstep = %i", *ip); \
+ fputs("\n\tkey = ", stdout); type_hex.dump(&v[0], stdout); \
+ fputs("\n\tnonce = ", stdout); type_hex.dump(&v[1], stdout); \
+ fputs("\n\theader = ", stdout); type_hex.dump(&v[2], stdout); \
+ fputs("\n\tciphertext = ", stdout); type_hex.dump(&v[4], stdout); \
+ fputs("\n\texp pt = ", stdout); type_hex.dump(&v[3], stdout); \
+ fputs("\n\tcalc pt = ", stdout); type_hex.dump(&d, stdout); \
+ fputs("\n\ttag = ", stdout); type_hex.dump(&v[5], stdout); \
+ printf("\n\tverify %s", win ? "ok" : "FAILED"); \
+ putchar('\n'); \
+ ok = 0; \
+ } \
+ } \
+ \
+ dstr_destroy(&d); dstr_destroy(&t); \
+ return (ok); \
+} \
+ \
+static test_chunk aeaddefs[] = { \
+ { name "-ocb1", ocb1verify, \
+ { &type_hex, &type_hex, &type_hex, &type_hex, \
+ &type_hex, &type_hex, 0 } }, \
+ { 0, 0, { 0 } } \
+}; \
+ \
+int main(int argc, char *argv[]) \
+{ \
+ ego(argv[0]); \
+ test_run(argc, argv, aeaddefs, SRCDIR"/t/" fname); \
+ return (0); \
+}
+
+#else
+# define OCB1_TESTX(PRE, pre, name, fname)
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
--- /dev/null
+/* -*-c-*-
+ *
+ * The OCB1 authenticated encryption mode
+ *
+ * (c) 2018 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*----- Notes on OCB1 -----------------------------------------------------*
+ *
+ * OCB was designed in 2001 by Phillip Rogaway, with Mihir Bellare and John
+ * Black, as a blockcipher-based authenticated encryption scheme which can
+ * operate on multiple message blocks in parallel and requires only a single
+ * blockcipher application per message block. It refines Charanjit Jutla's
+ * earlier IAPM, which was the first such mode to be proven secure. This
+ * version implements the `OCB.PMAC' mode described by Rogaway in 2002, which
+ * combines the original OCB with PMAC (Rogaway and Black, 2002) into a
+ * single authenticated-encryption with associated-data (AEAD) scheme.
+ *
+ * The patent situation on these efficient authenticated encryption schemes
+ * is fraught. IBM hold two patents on Jutla's pioneering work on `IACBC'
+ * and `IAPM' which can apply (a third was filed at least six years too
+ * late), and Virgil Gligor and Pompiliu Donescu hold patents on their `XECB'
+ * and `XCBC' modes; these may or may not apply to OCB. Rogaway himself
+ * holds US patents on various versions of OCB, but has issued free licences
+ * for free (`open source') software, and for all non-military use. I think
+ * Catacomb's implementation of OCB falls within the scope of the former
+ * licence.
+ *
+ * Confusingly, Rogaway's 2004 paper `Efficient Instantiations of Tweakable
+ * Blockciphers and Refinements to Modes OCB and PMAC' named the new versions
+ * of those modes `OCB1' and `PMAC1'. The 2011 paper by Krovetz and Rogaway,
+ * `The Software Performance of Authenticated-Encryption Modes' renamed the
+ * original 2001 version of OCB as `OCB1', and the 2004 version `OCB2', and
+ * introduced a new `OCB3'. I've decided to follow and extend the 2011
+ * naming, so `OCB1' refers to the 2001 OCB; the 2004 version would be
+ * `OCB2'.
+ *
+ * The OCB specification is clear about how OCB applies to arbitrary block
+ * sizes.
+ *
+ * OCB1 is a fairly well-behaved AEAD mode. It doesn't require
+ * precommentment to any lengths, and allows header data to be processed
+ * independently of any message. On the other hand, it only accepts nonces
+ * the same size as the underlying blockcipher's block size, and it buffers
+ * up to a whole block's worth of data internally, which somewhat complicates
+ * streaming.
+ */
+
+#ifndef CATACOMB_OCB1_H
+#define CATACOMB_OCB1_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+#include <mLib/buf.h>
+
+#ifndef CATACOMB_GAEAD_H
+# include "gaead.h"
+#endif
+
+#ifndef CATACOMB_OCB_H
+# include "ocb.h"
+#endif
+
+#ifndef CATACOMB_RSVR_H
+# include "rsvr.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @OCB1_DECL@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Creates declarations for OCB1 message-authentication mode.
+ */
+
+#define OCB1_STRUCTS(PRE, pre, keyty, aadty) \
+ \
+typedef struct keyty { \
+ pre##_ctx ctx; /* Underlying cipher context */ \
+ uint32 lxinv[PRE##_BLKSZ/4]; /* Final-block mask */ \
+ uint32 lmask[OCB_NCALC][PRE##_BLKSZ/4]; /* Precalculated masks */ \
+} keyty; \
+ \
+typedef struct aadty { \
+ keyty k; /* Processed key material */ \
+ uint32 o[PRE##_BLKSZ/4]; /* Current offset */ \
+ uint32 a[PRE##_BLKSZ/4]; /* Accumulator state */ \
+ octet b[PRE##_BLKSZ]; /* Input buffer */ \
+ unsigned long i; /* Block counter */ \
+ unsigned off; /* Offset into buffered data */ \
+} aadty;
+
+#define OCB1_DECL(PRE, pre) \
+ \
+OCB1_STRUCTS(PRE, pre, pre##_ocb1key, pre##_ocb1aadctx) \
+ \
+typedef struct pre##_ocb1ctx { \
+ /* This is the same as @pre_ocb1aadctx@ above, but the two are \
+ * logically distinct and shouldn't be muddled up. \
+ */ \
+ \
+ pre##_ocb1key k; /* Processed key material */ \
+ uint32 o[PRE##_BLKSZ/4]; /* Current offset */ \
+ uint32 a[PRE##_BLKSZ/4]; /* Accumulator state */ \
+ octet b[PRE##_BLKSZ]; /* Input buffer */ \
+ unsigned long i; /* Block counter */ \
+ unsigned off; /* Offset into buffered data */ \
+} pre##_ocb1ctx; \
+ \
+extern const rsvr_policy pre##_ocb1policy; \
+ \
+extern const octet pre##_ocb1noncesz[], pre##_ocb1tagsz[]; \
+ \
+/* --- @pre_ocb1setkey@ --- * \
+ * \
+ * Arguments: @pre_ocb1key *key@ = pointer to key block to fill in \
+ * @const void *k@ = pointer to key material \
+ * @size_t ksz@ = size of key material \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes an OCB1 key block. \
+ */ \
+ \
+extern void pre##_ocb1setkey(pre##_ocb1key */*key*/, \
+ const void */*k*/, size_t /*ksz*/); \
+ \
+/* --- @pre_ocb1aadinit@ --- * \
+ * \
+ * Arguments: @pre_ocb1aadctx *aad@ = pointer to AAD context \
+ * @const pre_ocb1key *key@ = pointer to key block \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes an OCB1 AAD (`additional authenticated \
+ * data') context associated with a given key. AAD \
+ * contexts can be copied and/or reused, saving time if \
+ * the AAD for number of messages has a common prefix. \
+ * \
+ * The @key@ doesn't need to be kept around, though \
+ * usually there'll at least be another copy in some OCB1 \
+ * operation context because the AAD on its own isn't much \
+ * good. \
+ */ \
+ \
+extern void pre##_ocb1aadinit(pre##_ocb1aadctx */*aad*/, \
+ const pre##_ocb1key */*key*/); \
+ \
+/* --- @pre_ocb1aadhash@ --- * \
+ * \
+ * Arguments: @pre_ocb1aadctx *aad@ = pointer to AAD context \
+ * @const void *p@ = pointer to AAD material \
+ * @size_t sz@ = length of AAD material \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Feeds AAD into the context. \
+ */ \
+ \
+extern void pre##_ocb1aadhash(pre##_ocb1aadctx */*aad*/, \
+ const void */*p*/, size_t /*sz*/); \
+ \
+/* --- @pre_ocb1aadtag@ --- * \
+ * \
+ * Arguments: @const pre_ocb1aadctx *aad@ = pointer to context block \
+ * @uint32 *u@ = where to write the tag \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Finishes processing AAD and produces a tag which can be \
+ * mixed with an OCB1 checksum. This function is exposed \
+ * for internal reasons and is not expected to be \
+ * generally useful. \
+ */ \
+ \
+extern void pre##_ocb1aadtag(const pre##_ocb1aadctx */*aad*/, \
+ uint32 */*t*/); \
+ \
+/* --- @pre_ocb1init@ --- * \
+ * \
+ * Arguments: @pre_ocb1ctx *ctx@ = pointer to OCB1 context \
+ * @const pre_ocb1key *key@ = pointer to key block \
+ * @const void *n@ = pointer to nonce \
+ * @size_t nsz@ = size of nonce \
+ * \
+ * Returns: Zero on success, @-1@ if the nonce length is bad. \
+ * \
+ * Use: Initialize an OCB1 operation context with a given key. \
+ * \
+ * The original key needn't be kept around any more. \
+ */ \
+ \
+extern int pre##_ocb1init(pre##_ocb1ctx */*ctx*/, \
+ const pre##_ocb1key */*k*/, \
+ const void */*n*/, size_t /*nsz*/); \
+ \
+/* --- @pre_ocb1reinit@ --- * \
+ * \
+ * Arguments: @pre_ocb1ctx *ctx@ = pointer to OCB1 context \
+ * @const void *n@ = pointer to nonce \
+ * @size_t nsz@ = size of nonce \
+ * \
+ * Returns: Zero on success, @-1@ if the nonce length is bad. \
+ * \
+ * Use: Reinitialize an OCB1 operation context, changing the \
+ * nonce. \
+ */ \
+ \
+extern int pre##_ocb1reinit(pre##_ocb1ctx */*ctx*/, \
+ const void */*n*/, size_t /*nsz*/); \
+ \
+/* --- @pre_ocb1encrypt@ --- * \
+ * \
+ * Arguments: @pre_ocb1ctx *ctx@ = pointer to OCB1 operation context \
+ * @const void *src@ = pointer to plaintext message chunk \
+ * @size_t sz@ = size of the plaintext \
+ * @buf *dst@ = a buffer to write the ciphertext to \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Encrypts a chunk of a plaintext message, writing a \
+ * chunk of ciphertext to the output buffer and updating \
+ * the operation state. \
+ * \
+ * Note that OCB1 delays output if its input is not a \
+ * whole number of blocks. This means that the output \
+ * might be smaller or larger the input by up to the block \
+ * size. \
+ */ \
+ \
+extern int pre##_ocb1encrypt(pre##_ocb1ctx */*ctx*/, \
+ const void */*src*/, size_t /*sz*/, \
+ buf */*dst*/); \
+ \
+/* --- @pre_ocb1decrypt@ --- * \
+ * \
+ * Arguments: @pre_ocb1ctx *ctx@ = pointer to OCB1 operation context \
+ * @const void *src@ = pointer to ciphertext message chunk \
+ * @size_t sz@ = size of the ciphertext \
+ * @buf *dst@ = a buffer to write the plaintext to \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Decrypts a chunk of a ciphertext message, writing a \
+ * chunk of plaintext to the output buffer and updating \
+ * the operation state. \
+ * \
+ * Note that OCB1 delays output if its input is not a \
+ * whole number of blocks. This means that the output \
+ * might be smaller or larger the input by up to the block \
+ * size. \
+ */ \
+ \
+extern int pre##_ocb1decrypt(pre##_ocb1ctx */*ctx*/, \
+ const void */*src*/, size_t /*sz*/, \
+ buf */*dst*/); \
+ \
+/* --- @pre_ocb1encryptdone@ --- * \
+ * \
+ * Arguments: @pre_ocb1ctx *ctx@ = pointer to an OCB1 context \
+ * @const pre_ocb1aadctx *aad@ = pointer to AAD context, \
+ * or null \
+ * @buf *dst@ = buffer for remaining ciphertext \
+ * @void *tag@ = where to write the tag \
+ * @size_t tsz@ = length of tag to store \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Completes an OCB1 encryption operation. The @aad@ \
+ * pointer may be null if there is no additional \
+ * authenticated data. OCB1 delays output, so this will \
+ * cause any remaining buffered plaintext to be encrypted \
+ * and written to @dst@. Anyway, the function will fail \
+ * if the output buffer is broken. \
+ */ \
+ \
+extern int pre##_ocb1encryptdone(pre##_ocb1ctx */*ctx*/, \
+ const pre##_ocb1aadctx */*aad*/, \
+ buf */*dst*/, \
+ void */*tag*/, size_t /*tsz*/); \
+ \
+/* --- @pre_ocb1decryptdone@ --- * \
+ * \
+ * Arguments: @pre_ocb1ctx *ctx@ = pointer to an OCB1 context \
+ * @const pre_ocb1aadctx *aad@ = pointer to AAD context, \
+ * or null \
+ * @buf *dst@ = buffer for remaining plaintext \
+ * @const void *tag@ = tag to verify \
+ * @size_t tsz@ = length of tag \
+ * \
+ * Returns: @+1@ for complete success; @0@ if tag verification \
+ * failed; @-1@ for other kinds of errors. \
+ * \
+ * Use: Completes an OCB1 decryption operation. The @aad@ \
+ * pointer may be null if there is no additional \
+ * authenticated data. OCB1 delays output, so this will \
+ * cause any remaining buffered ciphertext to be decrypted \
+ * and written to @dst@. Anyway, the function will fail \
+ * if the output buffer is broken. \
+ */ \
+ \
+extern int pre##_ocb1decryptdone(pre##_ocb1ctx */*ctx*/, \
+ const pre##_ocb1aadctx */*aad*/, \
+ buf */*dst*/, \
+ const void */*tag*/, size_t /*tsz*/); \
+ \
+/* --- Generic AEAD interface --- */ \
+ \
+extern const gcaead pre##_ocb1;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
--- /dev/null
+/* -*-c-*-
+ *
+ * The OCB3 authenticated encryption mode
+ *
+ * (c) 2018 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef CATACOMB_OCB3_DEF_H
+#define CATACOMB_OCB3_DEF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#ifndef CATACOMB_ARENA_H
+# include "arena.h"
+#endif
+
+#ifndef CATACOMB_BLKC_H
+# include "blkc.h"
+#endif
+
+#ifndef CATACOMB_CT_H
+# include "ct.h"
+#endif
+
+#ifndef CATACOMB_KEYSZ_H
+# include "keysz.h"
+#endif
+
+#ifndef CATACOMB_RSVR_H
+# include "rsvr.h"
+#endif
+
+#ifndef CATACOMB_PARANOIA_H
+# include "paranoia.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+#define OCB3_TSHIFT(PRE) BLKC_GLUE(OCB3_TSHIFT_, BLKC_BITS(PRE))
+#define OCB3_TSHIFT_64 2
+#define OCB3_TSHIFT_96 1
+#define OCB3_TSHIFT_128 1
+#define OCB3_TSHIFT_192 0
+#define OCB3_TSHIFT_256 0
+
+#define OCB3_STRETCHMASK(PRE) BLKC_GLUE(OCB3_STRETCHMASK_, BLKC_BITS(PRE))
+#define OCB3_STRETCHMASK_64 0x1f
+#define OCB3_STRETCHMASK_96 0x3f
+#define OCB3_STRETCHMASK_128 0x3f
+#define OCB3_STRETCHMASK_192 0x7f
+#define OCB3_STRETCHMASK_256 0xff
+
+#define OCB3_STRETCHSHIFT(PRE) BLKC_GLUE(OCB3_STRETCHSHIFT_, BLKC_BITS(PRE))
+#define OCB3_STRETCHSHIFT_64 25
+#define OCB3_STRETCHSHIFT_96 33
+#define OCB3_STRETCHSHIFT_128 8
+#define OCB3_STRETCHSHIFT_192 40
+#define OCB3_STRETCHSHIFT_256 1
+
+/* --- @OCB3_DEF@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Creates an implementation for the OCB3 authenticated-
+ * encryption mode.
+ */
+
+#define OCB3_DEF(PRE, pre) OCB3_DEFX(PRE, pre, #pre, #pre)
+
+#define OCB3_DEFX(PRE, pre, name, fname) \
+ \
+static const rsvr_policy pre##_ocb3policy = \
+ { 0, PRE##_BLKSZ, PRE##_BLKSZ }; \
+ \
+const octet \
+ pre##_ocb3noncesz[] = { KSZ_RANGE, OCB3_NSZMAX(PRE), \
+ 0, OCB3_NSZMAX(PRE), 1 }, \
+ pre##_ocb3tagsz[] = { KSZ_RANGE, PRE##_BLKSZ, 0, PRE##_BLKSZ, 1 }; \
+ \
+/* --- @pre_ocb3setkey@ --- * \
+ * \
+ * Arguments: @pre_ocb3key *key@ = pointer to OCB3 key block \
+ * @ocnst void *k@ = pointer to key material \
+ * @size_t ksz@ = size of key material \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes a OCB3 key. This can be used for \
+ * several encryption/or MAC operations. \
+ */ \
+ \
+void pre##_ocb3setkey(pre##_ocb3key *key, const void *k, size_t ksz) \
+{ \
+ unsigned i; \
+ \
+ pre##_init(&key->ctx, k, ksz); \
+ BLKC_ZERO(PRE, key->lstar); \
+ pre##_eblk(&key->ctx, key->lstar, key->lstar); \
+ BLKC_BLSHIFT(PRE, IRRED, key->ldollar, key->lstar); \
+ BLKC_BLSHIFT(PRE, IRRED, key->lmask[0], key->ldollar); \
+ for (i = 1; i < OCB_NCALC; i++) \
+ BLKC_BLSHIFT(PRE, IRRED, key->lmask[i], key->lmask[i - 1]); \
+} \
+ \
+/* --- @pre_ocb3aadinit@ --- * \
+ * \
+ * Arguments: @pre_ocb3aadctx *aad@ = pointer to context block \
+ * @pre_ocb3key *k@ = key block \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes an OCB3 AAD (`additional authenticated \
+ * data') context associated witha a given key. \
+ * AAD contexts can be copied and/or reused, saving time \
+ * if the AAD for a number of messages has a common \
+ * prefix. \
+ * \
+ * The @key@ doesn't need to be kept around. \
+ */ \
+ \
+void pre##_ocb3aadinit(pre##_ocb3aadctx *aad, const pre##_ocb3key *k) \
+{ \
+ aad->k = *k; \
+ aad->off = 0; aad->i = 1; \
+ BLKC_ZERO(PRE, aad->a); \
+ BLKC_ZERO(PRE, aad->o); \
+} \
+ \
+/* --- @pre_ocb3aadhash@ --- * \
+ * \
+ * Arguments: @pre_ocb3aadctx *aad@ = pointer to context block \
+ * @ocnst void *p@ = pointer to message buffer \
+ * @size_t sz@ = size of message buffer \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Hashes some AAD input data. \
+ */ \
+ \
+void pre##_ocb3aadhash(pre##_ocb3aadctx *aad, const void *p, size_t sz) \
+{ \
+ rsvr_state st; \
+ uint32 t[PRE##_BLKSZ/4]; \
+ const octet *q; \
+ \
+ rsvr_setup(&st, &pre##_ocb3policy, aad->b, &aad->off, p, sz); \
+ RSVR_DO(&st) while ((q = RSVR_NEXT(&st, PRE##_BLKSZ)) != 0) { \
+ OCB_OFFSET(PRE, aad->o, aad->k.lmask, aad->i++); \
+ BLKC_LOAD(PRE, t, q); BLKC_XMOVE(PRE, t, aad->o); \
+ pre##_eblk(&aad->k.ctx, t, t); \
+ BLKC_XMOVE(PRE, aad->a, t); \
+ } \
+} \
+ \
+/* --- @pre_ocb3augment@ --- * \
+ * \
+ * Arguments: @uint32 *nn@ = where to write the augmented nonce \
+ * @const octet *n@ = pointer to input nonce data \
+ * @size_t nsz@ = size of input nonce \
+ * @size_t tsz@ = tag length \
+ * \
+ * Returns: The nonce shift index. \
+ * \
+ * Use: Constructs the augmented base nonce, mixing in the tag \
+ * length appropriately. \
+ */ \
+ \
+static unsigned pre##_ocb3augment(uint32 *nn, const octet *n, \
+ size_t nsz, size_t tsz) \
+{ \
+ octet b[PRE##_BLKSZ] = { 0 }; \
+ uint32 t; \
+ unsigned nix; \
+ \
+ b[0] = 8*(tsz%PRE##_BLKSZ) << OCB3_TSHIFT(PRE); \
+ b[PRE##_BLKSZ - nsz - 1] |= 0x01; \
+ memcpy(b + PRE##_BLKSZ - nsz, n, nsz); \
+ BLKC_LOAD(PRE, nn, b); \
+ t = BLKC_BWORD(PRE, nn[PRE##_BLKSZ/4 - 1]); \
+ nix = t&OCB3_STRETCHMASK(PRE); \
+ t &= ~(uint32)OCB3_STRETCHMASK(PRE); \
+ nn[PRE##_BLKSZ/4 - 1] = BLKC_BWORD(PRE, t); \
+ return (nix); \
+} \
+ \
+/* --- @pre_ocb3stretch@ --- * \
+ * \
+ * Arguments: @pre_ocb3ctx *ctx@ = pointer to OCB3 context \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Stretches the augmented nonce. \
+ */ \
+ \
+static void pre##_ocb3stretch(pre##_ocb3ctx *ctx) \
+{ \
+ unsigned nw = OCB3_STRETCHSHIFT(PRE)/32, \
+ nl = OCB3_STRETCHSHIFT(PRE)%32, nr = 32 - nl; \
+ unsigned i; \
+ uint32 c = 0, t, u; \
+ \
+ pre##_eblk(&ctx->k.ctx, ctx->nbase, ctx->nstretch); \
+ for (i = 0; i < PRE##_BLKSZ/4; i++) \
+ ctx->nstretch[i] = BLKC_BWORD(PRE, ctx->nstretch[i]); \
+ i = PRE##_BLKSZ/4; \
+ while (i > PRE##_BLKSZ/4 - nw) \
+ { i--; ctx->nstretch[i + PRE##_BLKSZ/4] = ctx->nstretch[i]; } \
+ while (i--) { \
+ u = ctx->nstretch[i]; t = ctx->nstretch[i + nw]; \
+ ctx->nstretch[i + PRE##_BLKSZ/4] = u ^ (t << nl) ^ c; \
+ if (nr < 32) c = U32(t) >> nr; \
+ } \
+} \
+ \
+/* --- @pre_ocb3shift@ --- * \
+ * \
+ * Arguments: @pre_ocb3ctx *ctx@ = pointer to OCB3 context \
+ * @unsigned nix@ = nonce index \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Extracts a chunk out of the OCB3 stretched nonce and \
+ * writes it to @ctx->o@. \
+ */ \
+ \
+static void pre##_ocb3shift(pre##_ocb3ctx *ctx, unsigned nix) \
+{ \
+ unsigned nw = nix/32, nl = nix%32, nr = 32 - nl; \
+ uint32 c, t; \
+ unsigned i; \
+ \
+ i = PRE##_BLKSZ/4; \
+ if (nr < 32) c = U32(ctx->nstretch[PRE##_BLKSZ/4 + nw]) >> nr; \
+ else c = 0; \
+ while (i--) { \
+ t = ctx->nstretch[i + nw]; \
+ ctx->o[i] = BLKC_BWORD(PRE, (t << nl) | c); \
+ if (nr < 32) c = U32(t) >> nr; \
+ } \
+} \
+ \
+/* --- @pre_ocb3init@ --- * \
+ * \
+ * Arguments: @pre_ocb3ctx *ctx@ = pointer to OCB3 context \
+ * @const pre_ocb3key *key@ = pointer to key block \
+ * @const void *n@ = pointer to nonce \
+ * @size_t nsz@ = size of nonce \
+ * @size_t tsz@ = tag length \
+ * \
+ * Returns: Zero on success, @-1@ if the nonce or tag length is \
+ * bad. \
+ * \
+ * Use: Initialize an OCB3 operation context with a given key. \
+ * \
+ * The original key needn't be kept around any more. \
+ */ \
+ \
+int pre##_ocb3init(pre##_ocb3ctx *ctx, const pre##_ocb3key *k, \
+ const void *n, size_t nsz, size_t tsz) \
+{ \
+ unsigned nix; \
+ \
+ /* Preflight checking. */ \
+ if (nsz > OCB3_NSZMAX(PRE)) return (-1); \
+ if (tsz > PRE##_BLKSZ) return (-1); \
+ \
+ /* Copy over the blockcipher key. */ \
+ ctx->k = *k; \
+ \
+ /* Sort out the nonce. */ \
+ nix = pre##_ocb3augment(ctx->nbase, n, nsz, tsz); \
+ ctx->nix = nix; ctx->tsz = tsz; \
+ pre##_ocb3stretch(ctx); \
+ pre##_ocb3shift(ctx, nix); \
+ \
+ /* Other random things. */ \
+ ctx->off = 0; ctx->i = 1; \
+ BLKC_ZERO(PRE, ctx->a); \
+ \
+ /* Done. */ \
+ return (0); \
+} \
+ \
+/* --- @pre_ocb3reinit@ --- * \
+ * \
+ * Arguments: @pre_ocb3ctx *ctx@ = pointer to OCB3 context \
+ * @const void *n@ = pointer to nonce \
+ * @size_t nsz@ = size of nonce \
+ * @size_t tsz@ = tag length \
+ * \
+ * Returns: Zero on success, @-1@ if the nonce or tag length is \
+ * bad. \
+ * \
+ * Use: Reinitialize an OCB3 operation context, changing the \
+ * nonce and/or tag length. \
+ */ \
+ \
+int pre##_ocb3reinit(pre##_ocb3ctx *ctx, \
+ const void *n, size_t nsz, size_t tsz) \
+{ \
+ uint32 t[PRE##_BLKSZ/4]; \
+ unsigned nix, i; \
+ \
+ /* Preflight checking. */ \
+ if (nsz > OCB3_NSZMAX(PRE)) return (-1); \
+ if (tsz > PRE##_BLKSZ) return (-1); \
+ \
+ /* Sort out the nonce. */ \
+ nix = pre##_ocb3augment(t, n, nsz, tsz); \
+ for (i = 0; i < PRE##_BLKSZ/4; i++) { \
+ if (t[i] == ctx->nbase[i]) continue; \
+ ctx->nix = nix; ctx->tsz = tsz; \
+ BLKC_MOVE(PRE, ctx->nbase, t); pre##_ocb3stretch(ctx); \
+ break; \
+ } \
+ pre##_ocb3shift(ctx, nix); \
+ \
+ /* Other random things. */ \
+ ctx->off = 0; ctx->i = 1; \
+ BLKC_ZERO(PRE, ctx->a); \
+ \
+ /* Done. */ \
+ return (0); \
+} \
+ \
+/* --- @pre_ocb3step@ --- * \
+ * \
+ * Arguments: @pre_ocb3ctx *ctx@ = pointer to OCB3 context \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Reinitialize an OCB3 operation context, stepping to \
+ * the `next' nonce along. \
+ */ \
+ \
+void pre##_ocb3step(pre##_ocb3ctx *ctx) \
+{ \
+ /* Sort out the nonce. */ \
+ if (ctx->nix < OCB3_STRETCHMASK(PRE)) \
+ pre##_ocb3shift(ctx, ++ctx->nix); \
+ else { \
+ ctx->nix = 0; \
+ BLKC_BADD(PRE, ctx->nbase, OCB3_STRETCHMASK(PRE) + 1); \
+ pre##_ocb3stretch(ctx); \
+ pre##_ocb3shift(ctx, 0); \
+ } \
+ \
+ /* Other random things. */ \
+ ctx->off = 0; ctx->i = 1; \
+ BLKC_ZERO(PRE, ctx->a); \
+} \
+ \
+/* --- @pre_ocb3encrypt@ --- * \
+ * \
+ * Arguments: @pre_ocb3ctx *ctx@ = pointer to OCB3 operation context \
+ * @const void *src@ = pointer to plaintext message chunk \
+ * @size_t sz@ = size of the plaintext \
+ * @buf *dst@ = a buffer to write the ciphertext to \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Encrypts a chunk of a plaintext message, writing a \
+ * chunk of ciphertext to the output buffer and updating \
+ * the operation state. \
+ * \
+ * Note that OCB3 delays output if its input is not a \
+ * whole number of blocks. This means that the output \
+ * might be smaller or larger the input by up to the block \
+ * size. \
+ */ \
+ \
+int pre##_ocb3encrypt(pre##_ocb3ctx *ctx, \
+ const void *src, size_t sz, buf *dst) \
+{ \
+ rsvr_state st; \
+ size_t osz; \
+ uint32 t[PRE##_BLKSZ/4]; \
+ const octet *p; \
+ octet *q; \
+ \
+ /* Figure out what we're going to do. */ \
+ rsvr_setup(&st, &pre##_ocb3policy, ctx->b, &ctx->off, src, sz); \
+ \
+ /* Determine the output size and verify that there is enough \
+ * space. \
+ */ \
+ osz = st.plan.from_rsvr + st.plan.from_input; \
+ if (!osz) q = 0; \
+ else { q = buf_get(dst, osz); if (!q) return (-1); } \
+ \
+ /* Process the input in whole blocks at a time. */ \
+ RSVR_DO(&st) while ((p = RSVR_NEXT(&st, PRE##_BLKSZ)) != 0) { \
+ OCB_OFFSET(PRE, ctx->o, ctx->k.lmask, ctx->i++); \
+ BLKC_LOAD(PRE, t, p); BLKC_XMOVE(PRE, ctx->a, t); \
+ BLKC_XMOVE(PRE, t, ctx->o); pre##_eblk(&ctx->k.ctx, t, t); \
+ BLKC_XSTORE(PRE, q, t, ctx->o); q += PRE##_BLKSZ; \
+ } \
+ \
+ /* Done. */ \
+ return (0); \
+} \
+ \
+/* --- @pre_ocb3decrypt@ --- * \
+ * \
+ * Arguments: @pre_ocb3ctx *ctx@ = pointer to OCB3 operation context \
+ * @const void *src@ = pointer to ciphertext message chunk \
+ * @size_t sz@ = size of the ciphertext \
+ * @buf *dst@ = a buffer to write the plaintext to \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Decrypts a chunk of a ciphertext message, writing a \
+ * chunk of plaintext to the output buffer and updating \
+ * the operation state. \
+ * \
+ * Note that OCB3 delays output if its input is not a \
+ * whole number of blocks. This means that the output \
+ * might be smaller or larger the input by up to the block \
+ * size. \
+ */ \
+ \
+int pre##_ocb3decrypt(pre##_ocb3ctx *ctx, \
+ const void *src, size_t sz, buf *dst) \
+{ \
+ rsvr_state st; \
+ size_t osz; \
+ uint32 t[PRE##_BLKSZ/4]; \
+ const octet *p; \
+ octet *q; \
+ \
+ /* Figure out what we're going to do. */ \
+ rsvr_setup(&st, &pre##_ocb3policy, ctx->b, &ctx->off, src, sz); \
+ \
+ /* Determine the output size and verify that there is enough \
+ * space. \
+ */ \
+ osz = st.plan.from_rsvr + st.plan.from_input; \
+ if (!osz) q = 0; \
+ else { q = buf_get(dst, osz); if (!q) return (-1); } \
+ \
+ /* Process the input in whole blocks at a time. */ \
+ RSVR_DO(&st) while ((p = RSVR_NEXT(&st, PRE##_BLKSZ)) != 0) { \
+ OCB_OFFSET(PRE, ctx->o, ctx->k.lmask, ctx->i++); \
+ BLKC_LOAD(PRE, t, p); \
+ BLKC_XMOVE(PRE, t, ctx->o); pre##_dblk(&ctx->k.ctx, t, t); \
+ BLKC_XMOVE(PRE, t, ctx->o); BLKC_XMOVE(PRE, ctx->a, t); \
+ BLKC_STORE(PRE, q, t); q += PRE##_BLKSZ; \
+ } \
+ \
+ /* Done. */ \
+ return (0); \
+} \
+ \
+/* --- @pre_ocb3tag@ --- * \
+ * \
+ * Arguments: @pre_ocb3ctx *ctx@ = pointer to an OCB3 context \
+ * @const pre_ocb3aadctx *aad@ = pointer to AAD context, \
+ * or null \
+ * @buf *dst@ = buffer for remaining ciphertext \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Common end-of-message handling for encryption and \
+ * decryption. The caller is expected to have processed \
+ * the last partial block, mixing the padded plaintext \
+ * into the checksum and leaving the partial output in \
+ * the context's buffer: this function will write the \
+ * output to the caller's output buffer. It will compute \
+ * the final full-length tag and leave it in the \
+ * context's buffer. \
+ */ \
+ \
+static int pre##_ocb3tag(pre##_ocb3ctx *ctx, \
+ const pre##_ocb3aadctx *aad, buf *dst) \
+{ \
+ octet *q; \
+ \
+ /* Arrange space for the final output (if any). */ \
+ if (!ctx->off) { q = 0; if (!BOK(dst)) return (-1); } \
+ else { q = buf_get(dst, ctx->off); if (!q) return (-1); } \
+ \
+ /* Deal with whatever's left in the input buffer, if anything */ \
+ if (ctx->off) memcpy(q, ctx->b, ctx->off); \
+ \
+ /* Wrap up the checksum calculation. */ \
+ BLKC_XMOVE(PRE, ctx->o, ctx->k.ldollar); \
+ BLKC_XMOVE(PRE, ctx->a, ctx->o); \
+ pre##_eblk(&ctx->k.ctx, ctx->a, ctx->a); \
+ \
+ /* Finish off the AAD processing. */ \
+ if (aad) { \
+ if (aad->i) BLKC_XMOVE(PRE, ctx->a, aad->a); \
+ if (aad->off) { \
+ memcpy(ctx->b, aad->b, aad->off); \
+ ctx->b[aad->off] = 0x80; \
+ memset(ctx->b + aad->off + 1, 0, PRE##_BLKSZ - aad->off - 1); \
+ BLKC_LOAD(PRE, ctx->o, ctx->b); \
+ BLKC_XMOVE(PRE, ctx->o, aad->o); \
+ BLKC_XMOVE(PRE, ctx->o, ctx->k.lstar); \
+ pre##_eblk(&ctx->k.ctx, ctx->o, ctx->o); \
+ BLKC_XMOVE(PRE, ctx->a, ctx->o); \
+ } \
+ } \
+ \
+ /* Write the final tag. */ \
+ BLKC_STORE(PRE, ctx->b, ctx->a); \
+ \
+ /* Done. */ \
+ return (0); \
+} \
+ \
+/* --- @pre_ocb3encryptdone@ --- * \
+ * \
+ * Arguments: @pre_ocb3ctx *ctx@ = pointer to an OCB3 context \
+ * @const pre_ocb3aadctx *aad@ = pointer to AAD context, \
+ * or null \
+ * @buf *dst@ = buffer for remaining ciphertext \
+ * @void *tag@ = where to write the tag \
+ * @size_t tsz@ = length of tag to store \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Completes an OCB3 encryption operation. The @aad@ \
+ * pointer may be null if there is no additional \
+ * authenticated data. OCB3 delays output, so this will \
+ * cause any remaining buffered plaintext to be encrypted \
+ * and written to @dst@. Anyway, the function will fail \
+ * if the output buffer is broken. \
+ */ \
+ \
+int pre##_ocb3encryptdone(pre##_ocb3ctx *ctx, \
+ const pre##_ocb3aadctx *aad, buf *dst, \
+ void *tag, size_t tsz) \
+{ \
+ uint32 t[PRE##_BLKSZ/4], u[PRE##_BLKSZ]; \
+ \
+ /* Deal with any final partial block. */ \
+ if (ctx->off) { \
+ BLKC_XMOVE(PRE, ctx->o, ctx->k.lstar); \
+ ctx->b[ctx->off] = 0x80; \
+ memset(ctx->b + ctx->off + 1, 0, PRE##_BLKSZ - ctx->off - 1); \
+ BLKC_LOAD(PRE, t, ctx->b); \
+ BLKC_XMOVE(PRE, ctx->a, t); \
+ pre##_eblk(&ctx->k.ctx, ctx->o, u); \
+ BLKC_XSTORE(PRE, ctx->b, t, u); \
+ } \
+ \
+ /* Return the tag. */ \
+ assert(tsz == ctx->tsz); \
+ if (pre##_ocb3tag(ctx, aad, dst)) return (-1); \
+ memcpy(tag, ctx->b, tsz); \
+ return (0); \
+} \
+ \
+/* --- @pre_ocb3decryptdone@ --- * \
+ * \
+ * Arguments: @pre_ocb3ctx *ctx@ = pointer to an OCB3 context \
+ * @const pre_ocb3aadctx *aad@ = pointer to AAD context, \
+ * or null \
+ * @buf *dst@ = buffer for remaining plaintext \
+ * @const void *tag@ = tag to verify \
+ * @size_t tsz@ = length of tag \
+ * \
+ * Returns: @+1@ for complete success; @0@ if tag verification \
+ * failed; @-1@ for other kinds of errors. \
+ * \
+ * Use: Completes an OCB3 decryption operation. The @aad@ \
+ * pointer may be null if there is no additional \
+ * authenticated data. OCB3 delays output, so this will \
+ * cause any remaining buffered ciphertext to be decrypted \
+ * and written to @dst@. Anyway, the function will fail \
+ * if the output buffer is broken. \
+ */ \
+ \
+int pre##_ocb3decryptdone(pre##_ocb3ctx *ctx, \
+ const pre##_ocb3aadctx *aad, buf *dst, \
+ const void *tag, size_t tsz) \
+{ \
+ uint32 t[PRE##_BLKSZ/4], u[PRE##_BLKSZ]; \
+ \
+ /* Deal with any final partial block. */ \
+ if (ctx->off) { \
+ BLKC_XMOVE(PRE, ctx->o, ctx->k.lstar); \
+ BLKC_LOAD(PRE, t, ctx->b); \
+ pre##_eblk(&ctx->k.ctx, ctx->o, u); \
+ BLKC_XSTORE(PRE, ctx->b, t, u); \
+ ctx->b[ctx->off] = 0x80; \
+ memset(ctx->b + ctx->off + 1, 0, PRE##_BLKSZ - ctx->off - 1); \
+ BLKC_XLOAD(PRE, ctx->a, ctx->b); \
+ } \
+ \
+ /* Check the tag. */ \
+ assert(tsz == ctx->tsz); \
+ if (pre##_ocb3tag(ctx, aad, dst)) return (-1); \
+ if (ct_memeq(tag, ctx->b, ctx->tsz)) return (+1); \
+ else return (0); \
+} \
+ \
+/* --- Generic AEAD interface --- */ \
+ \
+typedef struct gactx { \
+ gaead_aad a; \
+ pre##_ocb3aadctx aad; \
+} gactx; \
+ \
+static gaead_aad *gadup(const gaead_aad *a) \
+ { gactx *aad = S_CREATE(gactx); *aad = *(gactx *)a; return (&aad->a); } \
+ \
+static void gahash(gaead_aad *a, const void *h, size_t hsz) \
+ { gactx *aad = (gactx *)a; pre##_ocb3aadhash(&aad->aad, h, hsz); } \
+ \
+static void gadestroy(gaead_aad *a) \
+ { gactx *aad = (gactx *)a; BURN(*aad); S_DESTROY(aad); } \
+ \
+static const gaead_aadops gaops = \
+ { &pre##_ocb3, gadup, gahash, gadestroy }; \
+ \
+static gaead_aad *gaad(const pre##_ocb3key *k) \
+{ \
+ gactx *aad = S_CREATE(gactx); \
+ aad->a.ops = &gaops; \
+ pre##_ocb3aadinit(&aad->aad, k); \
+ return (&aad->a); \
+} \
+ \
+typedef struct gectx { \
+ gaead_enc e; \
+ pre##_ocb3ctx ctx; \
+} gectx; \
+ \
+static gaead_aad *geaad(gaead_enc *e) \
+ { gectx *enc = (gectx *)e; return (gaad(&enc->ctx.k)); } \
+ \
+static int gereinit(gaead_enc *e, const void *n, size_t nsz, \
+ size_t hsz, size_t msz, size_t tsz) \
+{ \
+ gectx *enc = (gectx *)e; \
+ return (pre##_ocb3reinit(&enc->ctx, n, nsz, tsz)); \
+} \
+ \
+static int geenc(gaead_enc *e, const void *m, size_t msz, buf *b) \
+{ \
+ gectx *enc = (gectx *)e; \
+ return (pre##_ocb3encrypt(&enc->ctx, m, msz, b)); \
+} \
+ \
+static int gedone(gaead_enc *e, const gaead_aad *a, \
+ buf *b, void *t, size_t tsz) \
+{ \
+ gectx *enc = (gectx *)e; gactx *aad = (gactx *)a; \
+ assert(!a || a->ops == &gaops); \
+ return (pre##_ocb3encryptdone(&enc->ctx, a ? &aad->aad : 0, b, t, tsz)); \
+} \
+ \
+static void gedestroy(gaead_enc *e) \
+ { gectx *enc = (gectx *)e; BURN(*enc); S_DESTROY(enc); } \
+ \
+static const gaead_encops geops = \
+ { &pre##_ocb3, geaad, gereinit, geenc, gedone, gedestroy }; \
+ \
+typedef struct gdctx { \
+ gaead_dec d; \
+ pre##_ocb3ctx ctx; \
+} gdctx; \
+ \
+static gaead_aad *gdaad(gaead_dec *d) \
+ { gdctx *dec = (gdctx *)d; return (gaad(&dec->ctx.k)); } \
+ \
+static int gdreinit(gaead_dec *d, const void *n, size_t nsz, \
+ size_t hsz, size_t csz, size_t tsz) \
+{ \
+ gdctx *dec = (gdctx *)d; \
+ return (pre##_ocb3reinit(&dec->ctx, n, nsz, tsz)); \
+} \
+ \
+static int gddec(gaead_dec *d, const void *c, size_t csz, buf *b) \
+{ \
+ gdctx *dec = (gdctx *)d; \
+ return (pre##_ocb3decrypt(&dec->ctx, c, csz, b)); \
+} \
+ \
+static int gddone(gaead_dec *d, const gaead_aad *a, \
+ buf *b, const void *t, size_t tsz) \
+{ \
+ gdctx *dec = (gdctx *)d; gactx *aad = (gactx *)a; \
+ assert(!a || a->ops == &gaops); \
+ return (pre##_ocb3decryptdone(&dec->ctx, a ? &aad->aad : 0, b, t, tsz)); \
+} \
+ \
+static void gddestroy(gaead_dec *d) \
+ { gdctx *dec = (gdctx *)d; BURN(*dec); S_DESTROY(dec); } \
+ \
+static const gaead_decops gdops = \
+ { &pre##_ocb3, gdaad, gdreinit, gddec, gddone, gddestroy }; \
+ \
+typedef struct gkctx { \
+ gaead_key k; \
+ pre##_ocb3key key; \
+} gkctx; \
+ \
+static gaead_aad *gkaad(const gaead_key *k) \
+ { gkctx *key = (gkctx *)k; return (gaad(&key->key)); } \
+ \
+static gaead_enc *gkenc(const gaead_key *k, const void *n, size_t nsz, \
+ size_t hsz, size_t msz, size_t tsz) \
+{ \
+ gkctx *key = (gkctx *)k; \
+ gectx *enc = S_CREATE(gectx); \
+ \
+ enc->e.ops = &geops; \
+ if (pre##_ocb3init(&enc->ctx, &key->key, n, nsz, tsz)) \
+ { gedestroy(&enc->e); return (0); } \
+ return (&enc->e); \
+} \
+ \
+static gaead_dec *gkdec(const gaead_key *k, const void *n, size_t nsz, \
+ size_t hsz, size_t csz, size_t tsz) \
+{ \
+ gkctx *key = (gkctx *)k; \
+ gdctx *dec = S_CREATE(gdctx); \
+ \
+ dec->d.ops = &gdops; \
+ if (pre##_ocb3init(&dec->ctx, &key->key, n, nsz, tsz)) \
+ { gddestroy(&dec->d); return (0); } \
+ return (&dec->d); \
+} \
+ \
+static void gkdestroy(gaead_key *k) \
+ { gkctx *key = (gkctx *)k; BURN(*key); S_DESTROY(key); } \
+ \
+static const gaead_keyops gkops = \
+ { &pre##_ocb3, gkaad, gkenc, gkdec, gkdestroy }; \
+ \
+static gaead_key *gckey(const void *k, size_t ksz) \
+{ \
+ gkctx *key = S_CREATE(gkctx); \
+ key->k.ops = &gkops; \
+ pre##_ocb3setkey(&key->key, k, ksz); \
+ return (&key->k); \
+} \
+ \
+const gcaead pre##_ocb3 = { \
+ name "-ocb3", \
+ pre##_keysz, pre##_ocb3noncesz, pre##_ocb3tagsz, \
+ PRE##_BLKSZ, PRE##_BLKSZ - 1, 0, AEADF_PCTSZ, \
+ gckey \
+}; \
+ \
+OCB3_TESTX(PRE, pre, name, fname)
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#define OCB3_TEST(PRE, pre) OCB3_TESTX(PRE, pre, #pre, #pre)
+
+/* --- @OCB3_TEST@ --- *
+ *
+ * Arguments: @PRE, pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Standard test rig for OCB3 functions.
+ */
+
+#ifdef TEST_RIG
+
+#include <stdio.h>
+
+#include <mLib/dstr.h>
+#include <mLib/quis.h>
+#include <mLib/testrig.h>
+
+#define OCB3_TESTX(PRE, pre, name, fname) \
+ \
+static int ocb3verify(dstr *v) \
+{ \
+ pre##_ocb3key key; \
+ pre##_ocb3aadctx aad; \
+ pre##_ocb3ctx ctx; \
+ int ok = 1, win; \
+ int i; \
+ octet *p; \
+ int szs[] = { 1, 7, 192, -1, 0 }, *ip; \
+ size_t hsz, msz; \
+ dstr d = DSTR_INIT, t = DSTR_INIT; \
+ buf b; \
+ \
+ dstr_ensure(&d, v[4].len > v[3].len ? v[4].len : v[3].len); \
+ dstr_ensure(&t, v[5].len); t.len = v[5].len; \
+ \
+ pre##_ocb3setkey(&key, v[0].buf, v[0].len); \
+ \
+ for (ip = szs; *ip; ip++) { \
+ \
+ pre##_ocb3init(&ctx, &key, (octet *)v[1].buf, v[1].len, v[5].len); \
+ \
+ i = *ip; \
+ hsz = v[2].len; \
+ if (i == -1) i = hsz; \
+ if (i > hsz) continue; \
+ p = (octet *)v[2].buf; \
+ pre##_ocb3aadinit(&aad, &key); \
+ while (hsz) { \
+ if (i > hsz) i = hsz; \
+ pre##_ocb3aadhash(&aad, p, i); \
+ p += i; hsz -= i; \
+ } \
+ \
+ buf_init(&b, d.buf, d.sz); \
+ i = *ip; \
+ msz = v[3].len; \
+ if (i == -1) i = msz; \
+ if (i > msz) continue; \
+ p = (octet *)v[3].buf; \
+ while (msz) { \
+ if (i > msz) i = msz; \
+ if (pre##_ocb3encrypt(&ctx, p, i, &b)) { \
+ puts("!! ocb3encrypt reports failure"); \
+ goto fail_enc; \
+ } \
+ p += i; msz -= i; \
+ } \
+ \
+ if (pre##_ocb3encryptdone(&ctx, &aad, &b, (octet *)t.buf, t.len)) { \
+ puts("!! ocb3encryptdone reports failure"); \
+ goto fail_enc; \
+ } \
+ d.len = BLEN(&b); \
+ \
+ if (d.len != v[4].len || \
+ memcmp(d.buf, v[4].buf, v[4].len) != 0 || \
+ memcmp(t.buf, v[5].buf, v[5].len) != 0) { \
+ fail_enc: \
+ printf("\nfail encrypt:\n\tstep = %i", *ip); \
+ fputs("\n\tkey = ", stdout); type_hex.dump(&v[0], stdout); \
+ fputs("\n\tnonce = ", stdout); type_hex.dump(&v[1], stdout); \
+ fputs("\n\theader = ", stdout); type_hex.dump(&v[2], stdout); \
+ fputs("\n\tmessage = ", stdout); type_hex.dump(&v[3], stdout); \
+ fputs("\n\texp ct = ", stdout); type_hex.dump(&v[4], stdout); \
+ fputs("\n\tcalc ct = ", stdout); type_hex.dump(&d, stdout); \
+ fputs("\n\texp tag = ", stdout); type_hex.dump(&v[5], stdout); \
+ fputs("\n\tcalc tag = ", stdout); type_hex.dump(&t, stdout); \
+ putchar('\n'); \
+ ok = 0; \
+ } \
+ \
+ pre##_ocb3init(&ctx, &key, (octet *)v[1].buf, v[1].len, v[5].len); \
+ \
+ buf_init(&b, d.buf, d.sz); \
+ i = *ip; \
+ msz = v[4].len; \
+ if (i == -1) i = msz; \
+ if (i > msz) continue; \
+ p = (octet *)v[4].buf; \
+ while (msz) { \
+ if (i > msz) i = msz; \
+ if (pre##_ocb3decrypt(&ctx, p, i, &b)) { \
+ puts("!! ocb3decrypt reports failure"); \
+ win = 0; goto fail_dec; \
+ } \
+ p += i; msz -= i; \
+ } \
+ \
+ win = pre##_ocb3decryptdone(&ctx, &aad, &b, \
+ (octet *)v[5].buf, v[5].len); \
+ if (win < 0) { \
+ puts("!! ocb3decryptdone reports failure"); \
+ goto fail_dec; \
+ } \
+ d.len = BLEN(&b); \
+ \
+ if (d.len != v[3].len || !win || \
+ memcmp(d.buf, v[3].buf, v[3].len) != 0) { \
+ fail_dec: \
+ printf("\nfail decrypt:\n\tstep = %i", *ip); \
+ fputs("\n\tkey = ", stdout); type_hex.dump(&v[0], stdout); \
+ fputs("\n\tnonce = ", stdout); type_hex.dump(&v[1], stdout); \
+ fputs("\n\theader = ", stdout); type_hex.dump(&v[2], stdout); \
+ fputs("\n\tciphertext = ", stdout); type_hex.dump(&v[4], stdout); \
+ fputs("\n\texp pt = ", stdout); type_hex.dump(&v[3], stdout); \
+ fputs("\n\tcalc pt = ", stdout); type_hex.dump(&d, stdout); \
+ fputs("\n\ttag = ", stdout); type_hex.dump(&v[5], stdout); \
+ printf("\n\tverify %s", win ? "ok" : "FAILED"); \
+ putchar('\n'); \
+ ok = 0; \
+ } \
+ } \
+ \
+ dstr_destroy(&d); dstr_destroy(&t); \
+ return (ok); \
+} \
+ \
+static int ocb3mct(dstr *v) \
+{ \
+ unsigned ksz = *(unsigned long *)v[0].buf, tsz = v[1].len; \
+ dstr d = DSTR_INIT; \
+ octet z[128]; \
+ pre##_ocb3key k; \
+ pre##_ocb3ctx ctx; \
+ pre##_ocb3aadctx oaad, iaad; \
+ int rc; \
+ buf b; \
+ unsigned i; \
+ int ok = 1; \
+ \
+ dstr_ensure(&d, ksz); memset(d.buf, 0, ksz - 4); \
+ STORE32_B(d.buf + ksz - 4, 8*tsz); \
+ pre##_ocb3setkey(&k, d.buf, ksz); \
+ \
+ pre##_ocb3aadinit(&oaad, &k); \
+ \
+ dstr_ensure(&d, 128 + tsz); \
+ memset(z, 0, 128); \
+ pre##_ocb3init(&ctx, &k, z, PRE##_BLKSZ - 4, tsz); \
+ \
+ for (i = 0; i < 128; i++) { \
+ pre##_ocb3aadinit(&iaad, &k); pre##_ocb3aadhash(&iaad, z, i); \
+ \
+ pre##_ocb3step(&ctx); buf_init(&b, d.buf, i); \
+ rc = pre##_ocb3encrypt(&ctx, z, i, &b); if (rc) goto fail; \
+ rc = pre##_ocb3encryptdone(&ctx, &iaad, &b, d.buf + i, tsz); \
+ if (rc) goto fail; \
+ pre##_ocb3aadhash(&oaad, d.buf, i + tsz); \
+ \
+ pre##_ocb3step(&ctx); buf_init(&b, d.buf, i); \
+ rc = pre##_ocb3encrypt(&ctx, z, i, &b); if (rc) goto fail; \
+ rc = pre##_ocb3encryptdone(&ctx, 0, &b, d.buf + i, tsz); \
+ if (rc) goto fail; \
+ pre##_ocb3aadhash(&oaad, d.buf, i + tsz); \
+ \
+ pre##_ocb3step(&ctx); buf_init(&b, 0, 0); \
+ rc = pre##_ocb3encryptdone(&ctx, &iaad, &b, d.buf, tsz); \
+ if (rc) goto fail; \
+ pre##_ocb3aadhash(&oaad, d.buf, tsz); \
+ } \
+ \
+ pre##_ocb3step(&ctx); buf_init(&b, 0, 0); \
+ rc = pre##_ocb3encryptdone(&ctx, &oaad, &b, d.buf, tsz); \
+ if (rc) goto fail; \
+ \
+ d.len = tsz; \
+ if (memcmp(d.buf, v[1].buf, tsz) != 0) { \
+ fail: \
+ printf("\nfail mct: ksz = %u, tsz = %u", ksz, tsz); \
+ fputs("\n\texp tag = ", stdout); type_hex.dump(&v[1], stdout); \
+ fputs("\n\tcalc tag = ", stdout); type_hex.dump(&d, stdout); \
+ putchar('\n'); \
+ ok = 0; \
+ } \
+ \
+ return (ok); \
+} \
+ \
+static test_chunk aeaddefs[] = { \
+ { name "-ocb3", ocb3verify, \
+ { &type_hex, &type_hex, &type_hex, &type_hex, \
+ &type_hex, &type_hex, 0 } }, \
+ { name "-ocb3-mct", ocb3mct, \
+ { &type_ulong, &type_hex, 0 } }, \
+ { 0, 0, { 0 } } \
+}; \
+ \
+int main(int argc, char *argv[]) \
+{ \
+ ego(argv[0]); \
+ test_run(argc, argv, aeaddefs, SRCDIR"/t/" fname); \
+ return (0); \
+}
+
+#else
+# define OCB3_TESTX(PRE, pre, name, fname)
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
--- /dev/null
+/* -*-c-*-
+ *
+ * The OCB3 authenticated encryption mode
+ *
+ * (c) 2018 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*----- Notes on OCB3 -----------------------------------------------------*
+ *
+ * OCB3 was designed in 2011 by Phillip Rogaway and Ted Krovetz, building ten
+ * years of earlier work by Rogaway, Bellare, and Black, and refining Jutla's
+ * pioneering work on IACBC and IAPM. OCB3 is an efficient `authenticated
+ * encryption with associated data' (AEAD) scheme which requires only one
+ * blockcipher application per message block.
+ *
+ * The patent situation on these efficient authenticated encryption schemes
+ * is fraught. IBM hold two patents on Jutla's pioneering work on `IACBC'
+ * and `IAPM' which can apply (a third was filed at least six years too
+ * late), and Virgil Gligor and Pompiliu Donescu hold patents on their `XECB'
+ * and `XCBC' modes; these may or may not apply to OCB. Rogaway himself
+ * holds US patents on various versions of OCB, but has issued free licences
+ * for free (`open source') software, and for all non-military use. I think
+ * Catacomb's implementation of OCB falls within the scope of the former
+ * licence.
+ *
+ * OCB3 has optimized for short messages with `similar' nonces, where
+ * `similar' means `all but the low bits in the last byte are equal'; exactly
+ * how many bits depends on the block length in a rather complicated manner.
+ * This implementation supports this optimization through @pre_ocb3reinit@
+ * (which compares the new nonce against the old one to see whether it can
+ * make use of the similarity), and, more directly, through @pre_ocb3step@,
+ * which (effectively) advances the nonce as a big-endian counter.
+ *
+ * OCB3 was originally defined only for 128-bit blockciphers, and extending
+ * it to other sizes is nontrivial, but this has been done by Ted Krovetz in
+ * I-D draft-krovetz-ocb-wideblock-00 (following initial prompting from, err,
+ * me).
+ *
+ * OCB3 is a fairly well-behaved AEAD mode. It doesn't require
+ * precommentment to the header or message lengths, but does require
+ * precommitment to the tag length. It permits header data to be processed
+ * independently of any message. It only accepts nonces the same size as the
+ * underlying blockcipher's block size, and it buffers up to a whole block's
+ * worth of data internally, which somewhat complicates streaming.
+ */
+
+#ifndef CATACOMB_OCB3_H
+#define CATACOMB_OCB3_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+#include <mLib/buf.h>
+
+#ifndef CATACOMB_GAEAD_H
+# include "gaead.h"
+#endif
+
+#ifndef CATACOMB_OCB_H
+# include "ocb.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @OCB3_DECL@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Creates declarations for OCB3 message-authentication mode.
+ */
+
+#define OCB3_NSZMAX(PRE) (PRE##_BLKSZ - (PRE##_BLKSZ <= 16 ? 1 : 2))
+
+#define OCB3_DECL(PRE, pre) \
+ \
+typedef struct pre##_ocb3key { \
+ pre##_ctx ctx; /* Underlying cipher context */ \
+ uint32 lstar[PRE##_BLKSZ/4]; /* Partial-block mask */ \
+ uint32 ldollar[PRE##_BLKSZ/4]; /* Checksum mask */ \
+ uint32 lmask[OCB_NCALC][PRE##_BLKSZ/4]; /* Precalculated masks */ \
+} pre##_ocb3key; \
+ \
+typedef struct pre##_ocb3aadctx { \
+ pre##_ocb3key k; /* Processed key material */ \
+ uint32 o[PRE##_BLKSZ/4]; /* Current offset */ \
+ uint32 a[PRE##_BLKSZ/4]; /* Accumulator state */ \
+ octet b[PRE##_BLKSZ]; /* Input buffer */ \
+ unsigned long i; /* Block counter */ \
+ unsigned off; /* Offset into buffered data */ \
+} pre##_ocb3aadctx; \
+ \
+typedef struct pre##_ocb3ctx { \
+ pre##_ocb3key k; /* Processed key material */ \
+ unsigned nix, tsz; /* Nonce index and tag size */ \
+ uint32 nbase[PRE##_BLKSZ/2]; /* Current base nonce */ \
+ uint32 nstretch[PRE##_BLKSZ/2]; /* Stretched nonce material */ \
+ uint32 o[PRE##_BLKSZ/4]; /* Current offset */ \
+ uint32 a[PRE##_BLKSZ/4]; /* Accumulator state */ \
+ octet b[PRE##_BLKSZ]; /* Input buffer */ \
+ unsigned long i; /* Block counter */ \
+ unsigned off; /* Offset into buffered data */ \
+} pre##_ocb3ctx; \
+ \
+extern const octet pre##_ocb3noncesz[], pre##_ocb3tagsz[]; \
+ \
+/* --- @pre_ocb3setkey@ --- * \
+ * \
+ * Arguments: @pre_ocb3key *key@ = pointer to key block to fill in \
+ * @const void *k@ = pointer to key material \
+ * @size_t ksz@ = size of key material \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes an OCB3 key block. \
+ */ \
+ \
+extern void pre##_ocb3setkey(pre##_ocb3key */*key*/, \
+ const void */*k*/, size_t /*ksz*/); \
+ \
+/* --- @pre_ocb3aadinit@ --- * \
+ * \
+ * Arguments: @pre_ocb3aadctx *aad@ = pointer to AAD context \
+ * @const pre_ocb3key *key@ = pointer to key block \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes an OCB3 AAD (`additional authenticated \
+ * data') context associated with a given key. AAD \
+ * contexts can be copied and/or reused, saving time if \
+ * the AAD for number of messages has a common prefix. \
+ * \
+ * The @key@ doesn't need to be kept around, though \
+ * usually there'll at least be another copy in some OCB3 \
+ * operation context because the AAD on its own isn't much \
+ * good. \
+ */ \
+ \
+extern void pre##_ocb3aadinit(pre##_ocb3aadctx */*aad*/, \
+ const pre##_ocb3key */*key*/); \
+ \
+/* --- @pre_ocb3aadhash@ --- * \
+ * \
+ * Arguments: @pre_ocb3aadctx *aad@ = pointer to AAD context \
+ * @const void *p@ = pointer to AAD material \
+ * @size_t sz@ = length of AAD material \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Feeds AAD into the context. \
+ */ \
+ \
+extern void pre##_ocb3aadhash(pre##_ocb3aadctx */*aad*/, \
+ const void */*p*/, size_t /*sz*/); \
+ \
+/* --- @pre_ocb3init@ --- * \
+ * \
+ * Arguments: @pre_ocb3ctx *ctx@ = pointer to OCB3 context \
+ * @const pre_ocb3key *key@ = pointer to key block \
+ * @const void *n@ = pointer to nonce \
+ * @size_t nsz@ = size of nonce \
+ * @size_t tsz@ = tag length \
+ * \
+ * Returns: Zero on success, @-1@ if the nonce or tag length is \
+ * bad. \
+ * \
+ * Use: Initialize an OCB3 operation context with a given key. \
+ * \
+ * The original key needn't be kept around any more. \
+ */ \
+ \
+extern int pre##_ocb3init(pre##_ocb3ctx */*ctx*/, \
+ const pre##_ocb3key */*k*/, \
+ const void */*n*/, size_t /*nsz*/, \
+ size_t /*tsz*/); \
+ \
+/* --- @pre_ocb3reinit@ --- * \
+ * \
+ * Arguments: @pre_ocb3ctx *ctx@ = pointer to OCB3 context \
+ * @const void *n@ = pointer to nonce \
+ * @size_t nsz@ = size of nonce \
+ * @size_t tsz@ = tag length \
+ * \
+ * Returns: Zero on success, @-1@ if the nonce or tag length is \
+ * bad. \
+ * \
+ * Use: Reinitialize an OCB3 operation context, changing the \
+ * nonce and/or tag length. \
+ */ \
+ \
+extern int pre##_ocb3reinit(pre##_ocb3ctx */*ctx*/, \
+ const void */*n*/, size_t /*nsz*/, \
+ size_t /*tsz*/); \
+ \
+/* --- @pre_ocb3step@ --- * \
+ * \
+ * Arguments: @pre_ocb3ctx *ctx@ = pointer to OCB3 context \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Reinitialize an OCB3 operation context, stepping to \
+ * the `next' nonce along. \
+ */ \
+ \
+extern void pre##_ocb3step(pre##_ocb3ctx */*ctx*/); \
+ \
+/* --- @pre_ocb3encrypt@ --- * \
+ * \
+ * Arguments: @pre_ocb3ctx *ctx@ = pointer to OCB3 operation context \
+ * @const void *src@ = pointer to plaintext message chunk \
+ * @size_t sz@ = size of the plaintext \
+ * @buf *dst@ = a buffer to write the ciphertext to \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Encrypts a chunk of a plaintext message, writing a \
+ * chunk of ciphertext to the output buffer and updating \
+ * the operation state. \
+ * \
+ * Note that OCB3 delays output if its input is not a \
+ * whole number of blocks. This means that the output \
+ * might be smaller or larger the input by up to the block \
+ * size. \
+ */ \
+ \
+extern int pre##_ocb3encrypt(pre##_ocb3ctx */*ctx*/, \
+ const void */*src*/, size_t /*sz*/, \
+ buf */*dst*/); \
+ \
+/* --- @pre_ocb3decrypt@ --- * \
+ * \
+ * Arguments: @pre_ocb3ctx *ctx@ = pointer to OCB3 operation context \
+ * @const void *src@ = pointer to ciphertext message chunk \
+ * @size_t sz@ = size of the ciphertext \
+ * @buf *dst@ = a buffer to write the plaintext to \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Decrypts a chunk of a ciphertext message, writing a \
+ * chunk of plaintext to the output buffer and updating \
+ * the operation state. \
+ * \
+ * Note that OCB3 delays output if its input is not a \
+ * whole number of blocks. This means that the output \
+ * might be smaller or larger the input by up to the block \
+ * size. \
+ */ \
+ \
+extern int pre##_ocb3decrypt(pre##_ocb3ctx */*ctx*/, \
+ const void */*src*/, size_t /*sz*/, \
+ buf */*dst*/); \
+ \
+/* --- @pre_ocb3encryptdone@ --- * \
+ * \
+ * Arguments: @pre_ocb3ctx *ctx@ = pointer to an OCB3 context \
+ * @const pre_ocb3aadctx *aad@ = pointer to AAD context, \
+ * or null \
+ * @buf *dst@ = buffer for remaining ciphertext \
+ * @void *tag@ = where to write the tag \
+ * @size_t tsz@ = length of tag to store \
+ * \
+ * Returns: Zero on success; @-1@ on failure. \
+ * \
+ * Use: Completes an OCB3 encryption operation. The @aad@ \
+ * pointer may be null if there is no additional \
+ * authenticated data. OCB3 delays output, so this will \
+ * cause any remaining buffered plaintext to be encrypted \
+ * and written to @dst@. Anyway, the function will fail \
+ * if the output buffer is broken. \
+ */ \
+ \
+extern int pre##_ocb3encryptdone(pre##_ocb3ctx */*ctx*/, \
+ const pre##_ocb3aadctx */*aad*/, \
+ buf */*dst*/, \
+ void */*tag*/, size_t /*tsz*/); \
+ \
+/* --- @pre_ocb3decryptdone@ --- * \
+ * \
+ * Arguments: @pre_ocb3ctx *ctx@ = pointer to an OCB3 context \
+ * @const pre_ocb3aadctx *aad@ = pointer to AAD context, \
+ * or null \
+ * @buf *dst@ = buffer for remaining plaintext \
+ * @const void *tag@ = tag to verify \
+ * @size_t tsz@ = length of tag \
+ * \
+ * Returns: @+1@ for complete success; @0@ if tag verification \
+ * failed; @-1@ for other kinds of errors. \
+ * \
+ * Use: Completes an OCB3 decryption operation. The @aad@ \
+ * pointer may be null if there is no additional \
+ * authenticated data. OCB3 delays output, so this will \
+ * cause any remaining buffered ciphertext to be decrypted \
+ * and written to @dst@. Anyway, the function will fail \
+ * if the output buffer is broken. \
+ */ \
+ \
+extern int pre##_ocb3decryptdone(pre##_ocb3ctx */*ctx*/, \
+ const pre##_ocb3aadctx */*aad*/, \
+ buf */*dst*/, \
+ const void */*tag*/, size_t /*tsz*/); \
+ \
+/* --- Generic AEAD interface --- */ \
+ \
+extern const gcaead pre##_ocb3;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
# include "paranoia.h"
#endif
+#ifndef CATACOMB_RSVR_H
+# include "rsvr.h"
+#endif
+
/*----- Macros ------------------------------------------------------------*/
/* --- @OFB_DEF@ --- *
octet *p = iv; \
unsigned off = ctx->off; \
unsigned rest = PRE##_BLKSZ - off; \
- memcpy(p, ctx->iv + off, rest); \
- memcpy(p + rest, ctx->iv, off); \
+ \
+ memcpy(p, ctx->b + off, rest); \
+ memcpy(p + rest, ctx->b, off); \
} \
\
/* --- @pre_ofbsetiv@ --- * \
*/ \
\
void pre##_ofbsetiv(pre##_ofbctx *ctx, const void *iv) \
-{ \
- memcpy(ctx->iv, iv, PRE##_BLKSZ); \
- ctx->off = PRE##_BLKSZ; \
-} \
+ { memcpy(ctx->b, iv, PRE##_BLKSZ); ctx->off = 0; } \
\
/* --- @pre_ofbbdry@ --- * \
* \
\
void pre##_ofbbdry(pre##_ofbctx *ctx) \
{ \
- uint32 niv[PRE##_BLKSZ / 4]; \
- BLKC_LOAD(PRE, niv, ctx->iv); \
- pre##_eblk(&ctx->ctx, niv, niv); \
- BLKC_STORE(PRE, ctx->iv, niv); \
- ctx->off = PRE##_BLKSZ; \
- BURN(niv); \
+ uint32 t[PRE##_BLKSZ/4]; \
+ \
+ BLKC_LOAD(PRE, t, ctx->b); \
+ pre##_eblk(&ctx->ctx, t, t); \
+ BLKC_STORE(PRE, ctx->b, t); \
+ ctx->off = 0; \
+ BURN(t); \
} \
\
/* --- @pre_ofbsetkey@ --- * \
*/ \
\
void pre##_ofbsetkey(pre##_ofbctx *ctx, const pre##_ctx *k) \
-{ \
- ctx->ctx = *k; \
-} \
+ { ctx->ctx = *k; } \
\
/* --- @pre_ofbinit@ --- * \
* \
const void *iv) \
{ \
static const octet zero[PRE##_BLKSZ] = { 0 }; \
+ \
pre##_init(&ctx->ctx, key, sz); \
pre##_ofbsetiv(ctx, iv ? iv : zero); \
} \
* cipher as a random data generator. \
*/ \
\
+static const rsvr_policy pre##_ofbpolicy = { 0, PRE##_BLKSZ, PRE##_BLKSZ }; \
+ \
void pre##_ofbencrypt(pre##_ofbctx *ctx, \
- const void *src, void *dest, \
- size_t sz) \
+ const void *src, void *dest, \
+ size_t sz) \
{ \
- const octet *s = src; \
+ rsvr_plan plan; \
+ const octet *s = src, *p; \
octet *d = dest; \
- unsigned off = ctx->off; \
- \
- /* --- Empty blocks are trivial --- */ \
- \
- if (!sz) \
- return; \
- \
- /* --- If I can deal with the block from my buffer, do that --- */ \
- \
- if (sz < PRE##_BLKSZ - off) \
- goto small; \
- \
- /* --- Finish off what's left in my buffer --- */ \
- \
- if (!d) \
- sz -= PRE##_BLKSZ - off; \
- else { \
- while (off < PRE##_BLKSZ) { \
- register octet x = s ? *s++ : 0; \
- *d++ = ctx->iv[off++] ^ x; \
- sz--; \
+ uint32 t[PRE##_BLKSZ/4], u[PRE##_BLKSZ/4]; \
+ \
+ /* Construct a plan and prepare to follow through. */ \
+ rsvr_mkplan(&plan, &pre##_ofbpolicy, ctx->off, sz); \
+ BLKC_LOAD(PRE, t, ctx->b); \
+ \
+ /* Initial portion, fulfilled from the buffer. If the chunk is small \
+ * enough, then this will be the only portion. If the buffer is \
+ * currently empty, then we must prepare it. \
+ */ \
+ if (plan.head) { \
+ if (!ctx->off) { \
+ pre##_eblk(&ctx->ctx, t, t); \
+ BLKC_STORE(PRE, ctx->b, t); \
} \
+ p = ctx->b + ctx->off; ctx->off += plan.head; \
+ if (!d) /* nothing to do */; \
+ else if (!s) { memcpy(d, p, plan.head); d += plan.head; } \
+ else while (plan.head--) *d++ = *s++ ^ *p++; \
} \
\
- /* --- Main encryption loop --- */ \
- \
- { \
- uint32 iv[PRE##_BLKSZ / 4]; \
- BLKC_LOAD(PRE, iv, ctx->iv); \
- \
- for (;;) { \
- pre##_eblk(&ctx->ctx, iv, iv); \
- if (sz < PRE##_BLKSZ) \
- break; \
- if (d) { \
- if (!s) \
- BLKC_STORE(PRE, d, iv); \
- else { \
- uint32 x[PRE##_BLKSZ / 4]; \
- BLKC_LOAD(PRE, x, s); \
- BLKC_XSTORE(PRE, d, iv, x); \
- s += PRE##_BLKSZ; \
- } \
- d += PRE##_BLKSZ; \
- } \
- sz -= PRE##_BLKSZ; \
- } \
- \
- BLKC_STORE(PRE, ctx->iv, iv); \
- off = 0; \
+ /* If the buffer is all used, then reset it ready for next time. */ \
+ ctx->off -= plan.from_rsvr; \
+ \
+ /* Handle multiple whole blocks. */ \
+ if (!d) while (plan.from_input) { \
+ pre##_eblk(&ctx->ctx, t, t); \
+ plan.from_input -= PRE##_BLKSZ; \
+ } else if (!s) while (plan.from_input) { \
+ pre##_eblk(&ctx->ctx, t, t); \
+ BLKC_STORE(PRE, d, t); d += PRE##_BLKSZ; \
+ plan.from_input -= PRE##_BLKSZ; \
+ } else while (plan.from_input) { \
+ pre##_eblk(&ctx->ctx, t, t); \
+ BLKC_LOAD(PRE, u, s); s += PRE##_BLKSZ; \
+ BLKC_XSTORE(PRE, d, t, u); d += PRE##_BLKSZ; \
+ plan.from_input -= PRE##_BLKSZ; \
} \
\
- /* --- Tidying up the tail end --- */ \
- \
- if (sz) { \
- small: \
- if (!d) \
- off += sz; \
- else do { \
- register octet x = s ? *s++ : 0; \
- *d++ = ctx->iv[off++] ^ x; \
- sz--; \
- } while (sz); \
+ /* Final portion. Note that the buffer must be empty if there is a \
+ * tail, since otherwise the input data would have been part of the \
+ * head portion instad. */ \
+ if (!plan.tail) \
+ BLKC_STORE(PRE, ctx->b, t); \
+ else { \
+ pre##_eblk(&ctx->ctx, t, t); \
+ BLKC_STORE(PRE, ctx->b, t); \
+ p = ctx->b; ctx->off += plan.tail; \
+ if (!d) /* nothing to do */; \
+ else if (!s) { memcpy(d, p, plan.tail); d += plan.tail; } \
+ else while (plan.tail--) *d++ = *s++ ^ *p++; \
} \
- \
- /* --- Done --- */ \
- \
- ctx->off = off; \
- return; \
} \
\
/* --- Generic cipher interface --- */ \
} \
\
static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) \
-{ \
- gctx *g = (gctx *)c; \
- pre##_ofbencrypt(&g->k, s, t, sz); \
-} \
+ { gctx *g = (gctx *)c; pre##_ofbencrypt(&g->k, s, t, sz); } \
\
static void gdestroy(gcipher *c) \
-{ \
- gctx *g = (gctx *)c; \
- BURN(*g); \
- S_DESTROY(g); \
-} \
+ { gctx *g = (gctx *)c; BURN(*g); S_DESTROY(g); } \
\
static void gsetiv(gcipher *c, const void *iv) \
-{ \
- gctx *g = (gctx *)c; \
- pre##_ofbsetiv(&g->k, iv); \
-} \
+ { gctx *g = (gctx *)c; pre##_ofbsetiv(&g->k, iv); } \
\
static void gbdry(gcipher *c) \
{ \
} grctx; \
\
static void grdestroy(grand *r) \
-{ \
- grctx *g = (grctx *)r; \
- BURN(*g); \
- S_DESTROY(g); \
-} \
+ { grctx *g = (grctx *)r; BURN(*g); S_DESTROY(g); } \
\
static int grmisc(grand *r, unsigned op, ...) \
{ \
} \
\
static void grfill(grand *r, void *p, size_t sz) \
-{ \
- grctx *g = (grctx *)r; \
- pre##_ofbencrypt(&g->k, 0, p, sz); \
-} \
+ { grctx *g = (grctx *)r; pre##_ofbencrypt(&g->k, 0, p, sz); } \
\
static const grand_ops grops = { \
name "-ofb", \
#ifdef TEST_RIG
-#include <stdio.h>
-
-#include "daftstory.h"
+#include "modes-test.h"
/* --- @OFB_TEST@ --- *
*
* Use: Standard test rig for OFB functions.
*/
-#define OFB_TESTX(PRE, pre, name, fname) \
- \
-/* --- Initial plaintext for the test --- */ \
- \
-static const octet text[] = TEXT; \
- \
-/* --- Key and IV to use --- */ \
+#define OFB_TESTX(PRE, pre, name, fname) \
\
-static const octet key[] = KEY; \
-static const octet iv[] = IV; \
+static pre##_ctx key; \
+static pre##_ofbctx ctx; \
\
-/* --- Buffers for encryption and decryption output --- */ \
+static void pre##_ofb_test_setup(const octet *k, size_t ksz) \
+ { pre##_init(&key, k, ksz); pre##_ofbsetkey(&ctx, &key); } \
\
-static octet ct[sizeof(text)]; \
-static octet pt[sizeof(text)]; \
+static void pre##_ofb_test_reset(const octet *iv) \
+ { pre##_ofbsetiv(&ctx, iv); } \
\
-static void hexdump(const octet *p, size_t sz, size_t off) \
-{ \
- const octet *q = p + sz; \
- for (sz = 0; p < q; p++, sz++) { \
- printf("%02x", *p); \
- if ((off + sz + 1) % PRE##_BLKSZ == 0) \
- putchar(':'); \
- } \
-} \
+static void pre##_ofb_test_enc(const octet *s, octet *d, size_t sz) \
+ { pre##_ofbencrypt(&ctx, s, d, sz); } \
\
-int main(void) \
+int main(int argc, char *argv[]) \
{ \
- size_t sz = 0, rest; \
- pre##_ofbctx ctx; \
- int status = 0; \
- int done = 0; \
- pre##_ctx k; \
- \
- size_t keysz = PRE##_KEYSZ ? \
- PRE##_KEYSZ : strlen((const char *)key); \
- \
- fputs(name "-ofb: ", stdout); \
- \
- pre##_init(&k, key, keysz); \
- pre##_ofbsetkey(&ctx, &k); \
- \
- while (sz <= sizeof(text)) { \
- rest = sizeof(text) - sz; \
- memcpy(ct, text, sizeof(text)); \
- pre##_ofbsetiv(&ctx, iv); \
- pre##_ofbencrypt(&ctx, ct, ct, sz); \
- pre##_ofbencrypt(&ctx, ct + sz, ct + sz, rest); \
- memcpy(pt, ct, sizeof(text)); \
- pre##_ofbsetiv(&ctx, iv); \
- pre##_ofbencrypt(&ctx, pt, pt, rest); \
- pre##_ofbencrypt(&ctx, pt + rest, pt + rest, sz); \
- if (memcmp(pt, text, sizeof(text)) == 0) { \
- done++; \
- if (sizeof(text) < 40 || done % 8 == 0) \
- fputc('.', stdout); \
- if (done % 480 == 0) \
- fputs("\n\t", stdout); \
- fflush(stdout); \
- } else { \
- printf("\nError (sz = %lu)\n", (unsigned long)sz); \
- status = 1; \
- printf("\tplaintext = "); hexdump(text, sz, 0); \
- printf(", "); hexdump(text + sz, rest, sz); \
- fputc('\n', stdout); \
- printf("\tciphertext = "); hexdump(ct, sz, 0); \
- printf(", "); hexdump(ct + sz, rest, sz); \
- fputc('\n', stdout); \
- printf("\trecovered text = "); hexdump(pt, sz, 0); \
- printf(", "); hexdump(pt + sz, rest, sz); \
- fputc('\n', stdout); \
- fputc('\n', stdout); \
- } \
- if (sz < 63) \
- sz++; \
- else \
- sz += 9; \
- } \
- \
- fputs(status ? " failed\n" : " ok\n", stdout); \
- return (status); \
+ return test_encmode(fname "-ofb", PRE##_KEYSZ, PRE##_BLKSZ, 1, 0, \
+ pre##_ofb_test_setup, pre##_ofb_test_reset, \
+ pre##_ofb_test_enc, pre##_ofb_test_enc, \
+ argc, argv); \
}
#else
typedef struct pre##_ofbctx { \
pre##_ctx ctx; /* Underlying cipher context */ \
unsigned off; /* Current offset in buffer */ \
- octet iv[PRE##_BLKSZ]; /* Output buffer and IV */ \
+ octet b[PRE##_BLKSZ]; /* Output buffer and IV */ \
} pre##_ofbctx; \
\
/* --- @pre_ofbgetiv@ --- * \
--- /dev/null
+/* -*-c-*-
+ *
+ * The PMAC1 message authentication mode
+ *
+ * (c) 2018 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef CATACOMB_PMAC1_DEF_H
+#define CATACOMB_PMAC1_DEF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#ifndef CATACOMB_ARENA_H
+# include "arena.h"
+#endif
+
+#ifndef CATACOMB_BLKC_H
+# include "blkc.h"
+#endif
+
+#ifndef CATACOMB_PARANOIA_H
+# include "paranoia.h"
+#endif
+
+#ifndef CATACOMB_RSVR_H
+# include "rsvr.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @PMAC1_DEF@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Creates an implementation for the PMAC1 message-
+ * authentication mode.
+ */
+
+#define PMAC1_DEF(PRE, pre) PMAC1_DEFX(PRE, pre, #pre, #pre)
+
+#define PMAC1_DEFX(PRE, pre, name, fname) \
+ \
+OCB1_DECL(PRE, pre) \
+ \
+const rsvr_policy pre##_ocb1policy = \
+ { RSVRF_FULL, PRE##_BLKSZ, PRE##_BLKSZ }; \
+ \
+/* --- @pre_ocb1setkey@, @pre_pmac1setkey@ --- * \
+ * \
+ * Arguments: @pre_ocb1key *key@ = pointer to OCB1/PMAC1 key block \
+ * @ocnst void *k@ = pointer to key material \
+ * @size_t ksz@ = size of key material \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes a OCB1/PMAC1 key. This can be used for \
+ * several encryption and/or MAC operations. \
+ */ \
+ \
+void pre##_ocb1setkey(pre##_ocb1key *key, const void *k, size_t ksz) \
+{ \
+ unsigned i; \
+ \
+ pre##_init(&key->ctx, k, ksz); \
+ BLKC_ZERO(PRE, key->lmask[0]); \
+ pre##_eblk(&key->ctx, key->lmask[0], key->lmask[0]); \
+ BLKC_BRSHIFT(PRE, IRRED, key->lxinv, key->lmask[0]); \
+ for (i = 1; i < OCB_NCALC; i++) \
+ BLKC_BLSHIFT(PRE, IRRED, key->lmask[i], key->lmask[i - 1]); \
+} \
+void pre##_pmac1setkey(pre##_pmac1key *key, const void *k, size_t ksz) \
+ { pre##_ocb1setkey((pre##_ocb1key *)key, k, ksz); } \
+ \
+/* --- @pre_ocb1aadinit@, @pre_pmac1init --- * \
+ * \
+ * Arguments: @pre_ocb1aadctx *aad@ = pointer to context block \
+ * @pre_ocb1key *k@ = key block \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes an OCB1 AAD (`additional authenticated \
+ * data') or PMAC1 context associated witha a given key. \
+ * AAD contexts can be copied and/or reused, saving time \
+ * if the AAD for a number of messages has a common \
+ * prefix. \
+ * \
+ * The @key@ doesn't need to be kept around. \
+ */ \
+ \
+void pre##_ocb1aadinit(pre##_ocb1aadctx *aad, const pre##_ocb1key *k) \
+{ \
+ aad->k = *k; \
+ aad->off = 0; aad->i = 1; \
+ BLKC_ZERO(PRE, aad->a); \
+ BLKC_ZERO(PRE, aad->o); \
+} \
+void pre##_pmac1init(pre##_pmac1ctx *ctx, const pre##_pmac1key *k) \
+ { pre##_ocb1aadinit((pre##_ocb1aadctx *)ctx, (pre##_ocb1key *)k); } \
+ \
+/* --- @pre_ocb1aadhash@, @pre_pmac1hash@ --- * \
+ * \
+ * Arguments: @pre_ocb1aadctx *aad@ = pointer to context block \
+ * @ocnst void *p@ = pointer to message buffer \
+ * @size_t sz@ = size of message buffer \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Hashes some AAD input data. \
+ */ \
+ \
+void pre##_ocb1aadhash(pre##_ocb1aadctx *aad, const void *p, size_t sz) \
+{ \
+ rsvr_state st; \
+ uint32 t[PRE##_BLKSZ/4]; \
+ const octet *q; \
+ \
+ rsvr_setup(&st, &pre##_ocb1policy, aad->b, &aad->off, p, sz); \
+ RSVR_DO(&st) while ((q = RSVR_NEXT(&st, PRE##_BLKSZ)) != 0) { \
+ OCB_OFFSET(PRE, aad->o, aad->k.lmask, aad->i++); \
+ BLKC_LOAD(PRE, t, q); BLKC_XMOVE(PRE, t, aad->o); \
+ pre##_eblk(&aad->k.ctx, t, t); \
+ BLKC_XMOVE(PRE, aad->a, t); \
+ } \
+} \
+void pre##_pmac1hash(pre##_pmac1ctx *ctx, const void *p, size_t sz) \
+ { pre##_ocb1aadhash((pre##_ocb1aadctx *)ctx, p, sz); } \
+ \
+/* --- @pre_ocb1aadtag@ --- * \
+ * \
+ * Arguments: @const pre_ocb1aadctx *aad@ = pointer to context block \
+ * @uint32 *u@ = where to write the tag \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Finishes processing AAD and produces a tag which can be \
+ * mixed with an OCB1 checksum. This function is exposed \
+ * for internal reasons and is not expected to be \
+ * generally useful. \
+ */ \
+ \
+void pre##_ocb1aadtag(const pre##_ocb1aadctx *aad, uint32 *t) \
+{ \
+ octet b[PRE##_BLKSZ]; \
+ \
+ BLKC_MOVE(PRE, t, aad->a); \
+ if (aad->off == PRE##_BLKSZ) { \
+ BLKC_XLOAD(PRE, t, aad->b); \
+ BLKC_XMOVE(PRE, t, aad->k.lxinv); \
+ } else { \
+ memcpy(b, aad->b, aad->off); b[aad->off] = 0x80; \
+ memset(b + aad->off + 1, 0, PRE##_BLKSZ - aad->off - 1); \
+ BLKC_XLOAD(PRE, t, b); \
+ } \
+ pre##_eblk(&aad->k.ctx, t, t); \
+} \
+ \
+/* --- @pre_pmac1done@ --- * \
+ * \
+ * Arguments: @pre_pmac1ctx *ctx@ = pointer to context block \
+ * @void *t@ = where to write the tag \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Finishes a MAC operation and produces the tag. The \
+ * context is clobbered and can't be used for anything \
+ * useful any more. \
+ */ \
+ \
+void pre##_pmac1done(pre##_pmac1ctx *ctx, void *t) \
+{ \
+ uint32 u[PRE##_BLKSZ]; \
+ pre##_ocb1aadtag((pre##_ocb1aadctx *)ctx, u); BLKC_STORE(PRE, t, u); \
+} \
+ \
+/* --- Generic MAC interface --- */ \
+ \
+static const gmac_ops gkops; \
+static const ghash_ops gops; \
+ \
+typedef struct gkctx { \
+ gmac m; \
+ pre##_pmac1key k; \
+} gkctx; \
+ \
+typedef struct gctx { \
+ ghash h; \
+ pre##_pmac1ctx c; \
+ octet buf[PRE##_BLKSZ]; \
+} gctx; \
+ \
+static ghash *gkinit(gmac *m) \
+{ \
+ gkctx *gk = (gkctx *)m; \
+ gctx *g = S_CREATE(gctx); \
+ g->h.ops = &gops; \
+ pre##_pmac1init(&g->c, &gk->k); \
+ return (&g->h); \
+} \
+ \
+static gmac *gkey(const void *k, size_t sz) \
+{ \
+ gkctx *gk = S_CREATE(gkctx); \
+ gk->m.ops = &gkops; \
+ pre##_pmac1setkey(&gk->k, k, sz); \
+ return (&gk->m); \
+} \
+ \
+static void ghhash(ghash *h, const void *p, size_t sz) \
+ { gctx *g = (gctx *)h; pre##_pmac1hash(&g->c, p, sz); } \
+ \
+static octet *ghdone(ghash *h, void *buf) \
+{ \
+ gctx *g = (gctx *)h; \
+ if (!buf) buf = g->buf; \
+ pre##_pmac1done(&g->c, buf); \
+ return (buf); \
+} \
+ \
+static ghash *ghcopy(ghash *h) \
+{ \
+ gctx *g = (gctx *)h; \
+ gctx *gg = S_CREATE(gctx); \
+ memcpy(gg, g, sizeof(gctx)); \
+ return (&gg->h); \
+} \
+ \
+static void ghdestroy(ghash *h) \
+ { gctx *g = (gctx *)h; BURN(*g); S_DESTROY(g); } \
+ \
+static void gkdestroy(gmac *m) \
+ { gkctx *gk = (gkctx *)m; BURN(*gk); S_DESTROY(gk); } \
+ \
+static ghash *ghinit(void) \
+{ \
+ assert(((void)"Attempt to instantiate an unkeyed MAC", 0)); \
+ return (0); \
+} \
+ \
+const gcmac pre##_pmac1 = \
+ { name "-pmac1", PRE##_BLKSZ, pre##_keysz, gkey }; \
+static const gmac_ops gkops = { &pre##_pmac1, gkinit, gkdestroy }; \
+static const gchash gch = { name "-pmac1", PRE##_BLKSZ, ghinit }; \
+static const ghash_ops gops = \
+ { &gch, ghhash, ghdone, ghdestroy, ghcopy }; \
+ \
+PMAC1_TESTX(PRE, pre, name, fname)
+
+#define PMAC1_TEST(PRE, pre) HMAC_TESTX(PRE, pre, #pre, #pre)
+
+/* --- @PMAC1_TEST@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Standard test rig for PMAC1 functions.
+ */
+
+#ifdef TEST_RIG
+
+#include <stdio.h>
+
+#include <mLib/dstr.h>
+#include <mLib/quis.h>
+#include <mLib/testrig.h>
+
+#define PMAC1_TESTX(PRE, pre, name, fname) \
+ \
+static int macverify(dstr *v) \
+{ \
+ pre##_pmac1ctx cctx; \
+ pre##_pmac1key ckey; \
+ int ok = 1; \
+ int i; \
+ octet *p; \
+ int szs[] = { 1, 7, 192, -1, 0 }, *ip; \
+ size_t csz; \
+ dstr d; \
+ \
+ dstr_create(&d); \
+ dstr_ensure(&d, PRE##_BLKSZ); \
+ d.len = PRE##_BLKSZ; \
+ \
+ pre##_pmac1setkey(&ckey, v[0].buf, v[0].len); \
+ \
+ for (ip = szs; *ip; ip++) { \
+ i = *ip; \
+ csz = v[1].len; \
+ if (i == -1) \
+ i = csz; \
+ if (i > csz) \
+ continue; \
+ p = (octet *)v[1].buf; \
+ pre##_pmac1init(&cctx, &ckey); \
+ while (csz) { \
+ if (i > csz) \
+ i = csz; \
+ pre##_pmac1hash(&cctx, p, i); \
+ p += i; \
+ csz -= i; \
+ } \
+ pre##_pmac1done(&cctx, d.buf); \
+ if (memcmp(d.buf, v[2].buf, PRE##_BLKSZ) != 0) { \
+ printf("\nfail:\n\tstep = %i\n\tkey = ", *ip); \
+ type_hex.dump(&v[0], stdout); \
+ fputs("\n\tinput = ", stdout); \
+ type_hex.dump(&v[1], stdout); \
+ fputs("\n\texpected = ", stdout); \
+ type_hex.dump(&v[2], stdout); \
+ fputs("\n\tcomputed = ", stdout); \
+ type_hex.dump(&d, stdout); \
+ putchar('\n'); \
+ ok = 0; \
+ } \
+ } \
+ \
+ dstr_destroy(&d); \
+ return (ok); \
+} \
+ \
+static test_chunk macdefs[] = { \
+ { name "-pmac1", macverify, \
+ { &type_hex, &type_hex, &type_hex, 0 } }, \
+ { 0, 0, { 0 } } \
+}; \
+ \
+int main(int argc, char *argv[]) \
+{ \
+ ego(argv[0]); \
+ test_run(argc, argv, macdefs, SRCDIR"/t/" fname); \
+ return (0); \
+}
+
+#else
+# define PMAC1_TESTX(PRE, pre, name, fname)
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
--- /dev/null
+/* -*-c-*-
+ *
+ * The PMAC1 message authentication mode
+ *
+ * (c) 2018 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*----- Notes on PMAC1 ----------------------------------------------------*
+ *
+ * PMAC was designed in 2002 by John Black and Phillip Rogaway as a
+ * blockcipher-based MAC which can operate on multiple message blocks in
+ * parallel. Unfortunately, Rogaway applied for patents on PMAC, and as a
+ * result it saw limited adoption. Rogaway has since abandoned the patent
+ * applications, and PMAC is free for all uses.
+ *
+ * Confusingly, Rogaway's 2004 paper `Efficient Instantiations of Tweakable
+ * Blockciphers and Refinements to Modes OCB and PMAC' named the new versions
+ * of those modes `OCB1' and `PMAC1'. The 2011 paper by Krovetz and Rogaway,
+ * `The Software Performance of Authenticated-Encryption Modes' renamed the
+ * original 2001 version of OCB as `OCB1', and the 2004 version `OCB2', and
+ * introduced a new `OCB3', but does not mention PMAC. (PMAC is used as-is
+ * in the 2001 and 2004 versions of OCB, to process header data; the header
+ * processing in the 2011 version of OCB is not a secure standalone MAC, so
+ * there is no PMAC3.) I've decided to follow and extend the 2011 naming, so
+ * `PMAC1' refers to the 2002 PMAC; the 2004 version would be `PMAC2'.
+ *
+ * This implementation does not currently attempt to process blocks in
+ * parallel, though this is a possible future improvement.
+ */
+
+#ifndef CATACOMB_PMAC1_H
+#define CATACOMB_PMAC1_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_GMAC_H
+# include "gmac.h"
+#endif
+
+#ifndef CATACOMB_OCB1_H
+# include "ocb1.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @PMAC1_DECL@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Creates declarations for PMAC1 message-authentication mode.
+ *
+ * Most of these are aliases for OCB1 operations: see
+ * <catacomb/ocb1.h> for their documentation.
+ */
+
+#define PMAC1_DECL(PRE, pre) \
+ \
+OCB1_STRUCTS(PRE, pre, pre##_pmac1key, pre##_pmac1ctx) \
+ \
+extern void pre##_pmac1setkey(pre##_pmac1key */*key*/, \
+ const void */*k*/, size_t /*ksz*/); \
+ \
+extern void pre##_pmac1init(pre##_pmac1ctx */*ctx*/, \
+ const pre##_pmac1key */*k*/); \
+ \
+extern void pre##_pmac1hash(pre##_pmac1ctx */*ctx*/, \
+ const void */*p*/, size_t /*sz*/); \
+ \
+/* --- @pre_pmac1done@ --- * \
+ * \
+ * Arguments: @pre_pmac1ctx *ctx@ = pointer to PMAC1 context block \
+ * @void *t@ = where to write the tag \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Finishes a MAC operation and produces the tag. \
+ */ \
+ \
+extern void pre##_pmac1done(pre##_pmac1ctx */*ctx*/, void */*t*/); \
+ \
+/* --- Generic MAC interface --- */ \
+ \
+extern const gcmac pre##_pmac1;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
#include <string.h>
#include "poly1305.h"
+#include "rsvr.h"
/*----- Global variables --------------------------------------------------*/
ctx->count++;
}
+static const rsvr_policy pol = { 0, 16, 16 };
+
void poly1305_hash(poly1305_ctx *ctx, const void *p, size_t sz)
{
- const octet *pp = p;
- size_t n;
-
- if (ctx->nbuf) {
- if (sz < 16 - ctx->nbuf) {
- memcpy(ctx->buf + ctx->nbuf, p, sz);
- ctx->nbuf += sz;
- return;
- }
- n = 16 - ctx->nbuf;
- memcpy(ctx->buf + ctx->nbuf, pp, n);
- update_full(ctx, ctx->buf);
- pp += n; sz -= n;
- }
- while (sz >= 16) {
- update_full(ctx, pp);
- pp += 16; sz -= 16;
- }
- if (sz) memcpy(ctx->buf, pp, sz);
- ctx->nbuf = sz;
+ rsvr_state st;
+ const octet *q = p;
+
+ rsvr_setup(&st, &pol, &ctx->buf, &ctx->nbuf, p, sz);
+ RSVR_DO(&st) while ((q = RSVR_NEXT(&st, 16)) != 0) update_full(ctx, q);
}
/* --- @poly1305_flush@ --- *
/// MA 02111-1307, USA.
///--------------------------------------------------------------------------
-/// External definitions.
+/// Preliminaries.
#include "config.h"
#include "asm-common.h"
+ .arch armv8-a
+ .fpu crypto-neon-fp-armv8
+
.extern F(abort)
.extern F(rijndael_rcon)
+ .text
+
///--------------------------------------------------------------------------
/// Main code.
- .arch armv8-a
- .fpu crypto-neon-fp-armv8
-
/// The ARM crypto extension implements a little-endian version of AES
/// (though the manual doesn't actually spell this out and you have to
/// experiment), but Catacomb's internal interface presents as big-endian so
/// MA 02111-1307, USA.
///--------------------------------------------------------------------------
-/// External definitions.
+/// Preliminaries.
#include "config.h"
#include "asm-common.h"
+ .arch armv8-a+crypto
+
.extern F(abort)
.extern F(rijndael_rcon)
+ .text
+
///--------------------------------------------------------------------------
/// Main code.
- .arch armv8-a+crypto
-
/// The ARM crypto extension implements a little-endian version of AES
/// (though the manual doesn't actually spell this out and you have to
/// experiment), but Catacomb's internal interface presents as big-endian so
#if CPUFAM_X86 || CPUFAM_AMD64
extern setup__functype rijndael_setup_x86ish_aesni;
+extern setup__functype rijndael_setup_x86ish_aesni_avx;
#endif
#if CPUFAM_ARMEL && HAVE_AS_ARMV8_CRYPTO
extern setup__functype rijndael_setup_arm_crypto;
static setup__functype *pick_setup(void)
{
#if CPUFAM_X86 || CPUFAM_AMD64
+ DISPATCH_PICK_COND(rijndael_setup, rijndael_setup_x86ish_aesni_avx,
+ cpu_feature_p(CPUFEAT_X86_AVX) &&
+ cpu_feature_p(CPUFEAT_X86_AESNI));
DISPATCH_PICK_COND(rijndael_setup, rijndael_setup_x86ish_aesni,
cpu_feature_p(CPUFEAT_X86_AESNI));
#endif
/// MA 02111-1307, USA.
///--------------------------------------------------------------------------
-/// External definitions.
+/// Preliminaries.
#include "config.h"
#include "asm-common.h"
+ .arch .aes
+
.extern F(abort)
.extern F(rijndael_rcon)
+ .text
+
///--------------------------------------------------------------------------
/// Main code.
- .arch .aes
- .text
-
/// The AESNI instructions implement a little-endian version of AES, but
/// Catacomb's internal interface presents as big-endian so as to work better
/// with things like GCM. We therefore maintain the round keys in
///--------------------------------------------------------------------------
/// Key setup.
+FUNC(rijndael_setup_x86ish_aesni_avx)
+ vzeroupper // avoid penalty on `legacy' XMM access
+ endprologue
+ // and drop through...
+ENDFUNC
+
FUNC(rijndael_setup_x86ish_aesni)
#define SI WHOLE(si)
// Fourth word of the cycle, and seven or eight words of key. Do a
// byte substitution.
movd xmm0, eax
- pshufd xmm0, xmm0, SHUF(2, 1, 0, 3)
+ pshufd xmm0, xmm0, SHUF(3, 0, 1, 2)
aeskeygenassist xmm1, xmm0, 0
movd eax, xmm1
jmp 2f
// First word of the cycle. This is the complicated piece.
1: movd xmm0, eax
- pshufd xmm0, xmm0, SHUF(0, 3, 2, 1)
+ pshufd xmm0, xmm0, SHUF(1, 2, 3, 0)
aeskeygenassist xmm1, xmm0, 0
- pshufd xmm1, xmm1, SHUF(2, 1, 0, 3)
+ pshufd xmm1, xmm1, SHUF(3, 0, 1, 2)
movd eax, xmm1
xor al, [RCON]
inc RCON
/// Encrypting and decrypting blocks.
.macro encdec op, aes, koff
+ FUNC(rijndael_\op\()_x86ish_aesni_avx)
+ vzeroupper // avoid XMM penalties
+ endprologue
+ // and drop through...
+ ENDFUNC
+
FUNC(rijndael_\op\()_x86ish_aesni)
#if CPUFAM_X86
#if CPUFAM_X86 || CPUFAM_AMD64
extern rijndael_eblk__functype rijndael_eblk_x86ish_aesni;
extern rijndael_dblk__functype rijndael_dblk_x86ish_aesni;
+extern rijndael_eblk__functype rijndael_eblk_x86ish_aesni_avx;
+extern rijndael_dblk__functype rijndael_dblk_x86ish_aesni_avx;
#endif
#if CPUFAM_ARMEL && HAVE_AS_ARMV8_CRYPTO
extern rijndael_eblk__functype rijndael_eblk_arm_crypto;
static rijndael_eblk__functype *pick_eblk(void)
{
#if CPUFAM_X86 || CPUFAM_AMD64
+ DISPATCH_PICK_COND(rijndael_eblk, rijndael_eblk_x86ish_aesni_avx,
+ cpu_feature_p(CPUFEAT_X86_AVX) &&
+ cpu_feature_p(CPUFEAT_X86_AESNI));
DISPATCH_PICK_COND(rijndael_eblk, rijndael_eblk_x86ish_aesni,
cpu_feature_p(CPUFEAT_X86_AESNI));
#endif
static rijndael_dblk__functype *pick_dblk(void)
{
#if CPUFAM_X86 || CPUFAM_AMD64
+ DISPATCH_PICK_COND(rijndael_dblk, rijndael_dblk_x86ish_aesni_avx,
+ cpu_feature_p(CPUFEAT_X86_AVX) &&
+ cpu_feature_p(CPUFEAT_X86_AESNI));
DISPATCH_PICK_COND(rijndael_dblk, rijndael_dblk_x86ish_aesni,
cpu_feature_p(CPUFEAT_X86_AESNI));
#endif
/// MA 02111-1307, USA.
///--------------------------------------------------------------------------
-/// External definitions.
+/// Preliminaries.
#include "config.h"
#include "asm-common.h"
-///--------------------------------------------------------------------------
-/// Main.code.
-
.arch armv7-a
.fpu neon
+
.text
+///--------------------------------------------------------------------------
+/// Main.code.
+
FUNC(salsa20_core_arm_neon)
// Arguments are in registers.
/// MA 02111-1307, USA.
///--------------------------------------------------------------------------
-/// External definitions.
+/// Preliminaries.
#include "config.h"
#include "asm-common.h"
-///--------------------------------------------------------------------------
-/// Main.code.
-
.arch armv8-a
+
.text
+///--------------------------------------------------------------------------
+/// Main.code.
+
FUNC(salsa20_core_arm64)
// Arguments are in registers.
*/
#define SALSA20_PREPBUF(ctx, a) do { \
int _i; \
- for (_i = 0; _i < 16; _i++) STORE32_L((ctx)->buf + 4*_i, (a)[_i]); \
- (ctx)->bufi = 0; \
+ for (_i = 0; _i < 16; _i++) STORE32_L((ctx)->b + 4*_i, (a)[_i]); \
+ (ctx)->off = 0; \
} while (0)
/* Write at most @n@ bytes of buffered output from the context @ctx@ to the
* @n@ is decreased appropriately.
*/
#define SALSA20_OUTBUF(ctx, d, s, n) do { \
- size_t _n = (n), _left = SALSA20_OUTSZ - (ctx)->bufi; \
- if (_n > _left) _n = _left; \
- (n) -= _n; \
- if (!(d)) (ctx)->bufi += _n; \
- else if (s) while (_n--) *(d)++ = (ctx)->buf[(ctx)->bufi++] ^ *(s)++; \
- else while (_n--) *(d)++ = (ctx)->buf[(ctx)->bufi++]; \
+ const octet *_p = (ctx)->b + (ctx)->off; \
+ size_t _n = (n); \
+ \
+ (ctx)->off += _n; \
+ if (!(d)) /* nothing to do */; \
+ else if (!(s)) { memcpy((d), _p, _n); (d) += _n; } \
+ else while (_n--) *(d)++ = *(s)++ ^ *_p++; \
} while (0)
/*----- Variants and naming -----------------------------------------------*/
--- /dev/null
+/* -*-c-*-
+ *
+ * AEAD schemes based on Salsa20 and Poly1305
+ *
+ * (c) 2018 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb. If not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include "latinpoly-def.h"
+#include "salsa20.h"
+
+/*----- Main code ---------------------------------------------------------*/
+
+LATINPOLY_DEF(salsa20, salsa20, "salsa20")
+LATINPOLY_DEF(salsa2012, salsa20, "salsa20/12")
+LATINPOLY_DEF(salsa208, salsa20, "salsa20/8")
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <mLib/quis.h>
+#include <mLib/testrig.h>
+#include "latinpoly-test.h"
+
+static int check_salsa20_poly1305(dstr *v)
+ { return latinpoly_test(&salsa20_poly1305, v); }
+static int check_salsa2012_poly1305(dstr *v)
+ { return latinpoly_test(&salsa2012_poly1305, v); }
+static int check_salsa208_poly1305(dstr *v)
+ { return latinpoly_test(&salsa208_poly1305, v); }
+static int check_salsa20_naclbox(dstr *v)
+ { return latinpoly_test(&salsa20_naclbox, v); }
+static int check_salsa2012_naclbox(dstr *v)
+ { return latinpoly_test(&salsa2012_naclbox, v); }
+static int check_salsa208_naclbox(dstr *v)
+ { return latinpoly_test(&salsa208_naclbox, v); }
+
+static const test_chunk tests[] = {
+ { "salsa20-poly1305", check_salsa20_poly1305,
+ { &type_hex, &type_hex, &type_hex, &type_hex, &type_hex, &type_hex } },
+ { "salsa20/12-poly1305", check_salsa2012_poly1305,
+ { &type_hex, &type_hex, &type_hex, &type_hex, &type_hex, &type_hex } },
+ { "salsa20/8-poly1305", check_salsa208_poly1305,
+ { &type_hex, &type_hex, &type_hex, &type_hex, &type_hex, &type_hex } },
+ { "salsa20-naclbox", check_salsa20_naclbox,
+ { &type_hex, &type_hex, &type_hex, &type_hex, &type_hex, &type_hex } },
+ { "salsa20/12-naclbox", check_salsa2012_naclbox,
+ { &type_hex, &type_hex, &type_hex, &type_hex, &type_hex, &type_hex } },
+ { "salsa20/8-nacblox", check_salsa208_naclbox,
+ { &type_hex, &type_hex, &type_hex, &type_hex, &type_hex, &type_hex } },
+ { 0, 0, { 0 } }
+#undef TEST
+};
+
+int main(int argc, char *argv[])
+{
+ ego(argv[0]);
+ test_run(argc, argv, tests, SRCDIR"/t/salsa20");
+ return (0);
+}
+
+#endif
+/*----- That's all, folks -------------------------------------------------*/
/// MA 02111-1307, USA.
///--------------------------------------------------------------------------
-/// External definitions.
+/// Preliminaries.
#include "config.h"
#include "asm-common.h"
+ .text
+
///--------------------------------------------------------------------------
/// Main code.
- .arch pentium4
- .text
+FUNC(salsa20_core_x86ish_avx)
+ .arch .avx
+ vzeroupper
+ endprologue
+ // drop through...
+ENDFUNC
+
+ .arch pentium4
FUNC(salsa20_core_x86ish_sse2)
# define SAVE3 [esp + 16]
pushreg ebp
- setfp ebp
+ setfp
sub esp, 32
mov IN, [ebp + 12]
mov OUT, [ebp + 16]
// d ^= (c + b) <<< 13
movdqa xmm4, xmm2
paddd xmm4, xmm1
- pshufd xmm1, xmm1, SHUF(2, 1, 0, 3)
+ pshufd xmm1, xmm1, SHUF(3, 0, 1, 2)
movdqa xmm5, xmm4
pslld xmm4, 13
psrld xmm5, 19
// a ^= (d + c) <<< 18
movdqa xmm4, xmm3
- pshufd xmm3, xmm3, SHUF(0, 3, 2, 1)
+ pshufd xmm3, xmm3, SHUF(1, 2, 3, 0)
paddd xmm4, xmm2
- pshufd xmm2, xmm2, SHUF(1, 0, 3, 2)
+ pshufd xmm2, xmm2, SHUF(2, 3, 0, 1)
movdqa xmm5, xmm4
pslld xmm4, 18
psrld xmm5, 14
// d ^= (c + b) <<< 13
movdqa xmm4, xmm2
paddd xmm4, xmm3
- pshufd xmm3, xmm3, SHUF(2, 1, 0, 3)
+ pshufd xmm3, xmm3, SHUF(3, 0, 1, 2)
movdqa xmm5, xmm4
pslld xmm4, 13
psrld xmm5, 19
// a ^= (d + c) <<< 18
movdqa xmm4, xmm1
- pshufd xmm1, xmm1, SHUF(0, 3, 2, 1)
+ pshufd xmm1, xmm1, SHUF(1, 2, 3, 0)
paddd xmm4, xmm2
- pshufd xmm2, xmm2, SHUF(1, 0, 3, 2)
+ pshufd xmm2, xmm2, SHUF(2, 3, 0, 1)
movdqa xmm5, xmm4
pslld xmm4, 18
psrld xmm5, 14
// input. This can be done by juggling values in registers, with the
// following fancy footwork: some row rotations, a transpose, and
// some more rotations.
- pshufd xmm1, xmm1, SHUF(2, 1, 0, 3) // 3, 4, 9, 14
- pshufd xmm2, xmm2, SHUF(1, 0, 3, 2) // 2, 7, 8, 13
- pshufd xmm3, xmm3, SHUF(0, 3, 2, 1) // 1, 6, 11, 12
+ pshufd xmm1, xmm1, SHUF(3, 0, 1, 2) // 3, 4, 9, 14
+ pshufd xmm2, xmm2, SHUF(2, 3, 0, 1) // 2, 7, 8, 13
+ pshufd xmm3, xmm3, SHUF(1, 2, 3, 0) // 1, 6, 11, 12
movdqa xmm4, xmm0
movdqa xmm5, xmm3
punpckhdq xmm1, xmm3 // 5, 6, 7, 4
punpckhdq xmm2, xmm5 // 15, 12, 13, 14
- pshufd xmm1, xmm1, SHUF(2, 1, 0, 3) // 4, 5, 6, 7
- pshufd xmm4, xmm4, SHUF(1, 0, 3, 2) // 8, 9, 10, 11
- pshufd xmm2, xmm2, SHUF(0, 3, 2, 1) // 12, 13, 14, 15
+ pshufd xmm1, xmm1, SHUF(3, 0, 1, 2) // 4, 5, 6, 7
+ pshufd xmm4, xmm4, SHUF(2, 3, 0, 1) // 8, 9, 10, 11
+ pshufd xmm2, xmm2, SHUF(1, 2, 3, 0) // 12, 13, 14, 15
// Finally we have to write out the result.
movdqu [OUT + 0], xmm0
#include "grand.h"
#include "keysz.h"
#include "paranoia.h"
+#include "rsvr.h"
#include "salsa20.h"
#include "salsa20-core.h"
#if CPUFAM_X86 || CPUFAM_AMD64
extern core__functype salsa20_core_x86ish_sse2;
+extern core__functype salsa20_core_x86ish_avx;
#endif
#if CPUFAM_ARMEL
static core__functype *pick_core(void)
{
#if CPUFAM_X86 || CPUFAM_AMD64
+ DISPATCH_PICK_COND(salsa20_core, salsa20_core_x86ish_avx,
+ cpu_feature_p(CPUFEAT_X86_AVX));
DISPATCH_PICK_COND(salsa20_core, salsa20_core_x86ish_sse2,
cpu_feature_p(CPUFEAT_X86_SSE2));
#endif
/*----- Salsa20 implementation --------------------------------------------*/
+static const octet zerononce[XSALSA20_NONCESZ];
+
/* --- @salsa20_init@ --- *
*
* Arguments: @salsa20_ctx *ctx@ = context to fill in
void salsa20_init(salsa20_ctx *ctx, const void *key, size_t ksz,
const void *nonce)
{
- static const octet zerononce[SALSA20_NONCESZ];
-
populate(ctx->a, key, ksz);
salsa20_setnonce(ctx, nonce ? nonce : zerononce);
}
void salsa20_seeku64(salsa20_ctx *ctx, kludge64 i)
{
ctx->a[8] = LO64(i); ctx->a[5] = HI64(i);
- ctx->bufi = SALSA20_OUTSZ;
+ ctx->off = 0;
}
void salsa20_seek_ietf(salsa20_ctx *ctx, uint32 i)
* to @dest@.
*/
+static const rsvr_policy policy = { 0, SALSA20_OUTSZ, SALSA20_OUTSZ };
+
#define SALSA20_ENCRYPT(r, ctx, src, dest, sz) \
SALSA20_DECOR(salsa20, r, _encrypt)(ctx, src, dest, sz)
#define DEFENCRYPT(r) \
salsa20_matrix b; \
const octet *s = src; \
octet *d = dest; \
- size_t n; \
+ rsvr_plan plan; \
kludge64 pos, delta; \
\
- SALSA20_OUTBUF(ctx, d, s, sz); \
- if (!sz) return; \
- \
- if (!dest) { \
- n = sz/SALSA20_OUTSZ; \
- pos = salsa20_tellu64(ctx); \
- ASSIGN64(delta, n); \
- ADD64(pos, pos, delta); \
- salsa20_seeku64(ctx, pos); \
- sz = sz%SALSA20_OUTSZ; \
- } else if (!src) { \
- while (sz >= SALSA20_OUTSZ) { \
- core(r, ctx->a, b); \
- SALSA20_STEP(ctx->a); \
- SALSA20_GENFULL(b, d); \
- sz -= SALSA20_OUTSZ; \
+ rsvr_mkplan(&plan, &policy, ctx->off, sz); \
+ \
+ if (plan.head) { \
+ if (!ctx->off) { \
+ core(r, ctx->a, b); SALSA20_STEP(ctx->a); \
+ SALSA20_PREPBUF(ctx, b); \
} \
- } else { \
- while (sz >= SALSA20_OUTSZ) { \
- core(r, ctx->a, b); \
- SALSA20_STEP(ctx->a); \
- SALSA20_MIXFULL(b, d, s); \
- sz -= SALSA20_OUTSZ; \
+ SALSA20_OUTBUF(ctx, d, s, plan.head); \
+ } \
+ \
+ ctx->off -= plan.from_rsvr; \
+ \
+ if (!d) { \
+ if (plan.from_input) { \
+ pos = salsa20_tellu64(ctx); \
+ ASSIGN64(delta, plan.from_input/SALSA20_OUTSZ); \
+ ADD64(pos, pos, delta); \
+ salsa20_seeku64(ctx, pos); \
} \
+ } else if (!s) while (plan.from_input) { \
+ core(r, ctx->a, b); SALSA20_STEP(ctx->a); \
+ SALSA20_GENFULL(b, d); plan.from_input -= SALSA20_OUTSZ; \
+ } else while (plan.from_input) { \
+ core(r, ctx->a, b); SALSA20_STEP(ctx->a); \
+ SALSA20_MIXFULL(b, d, s); plan.from_input -= SALSA20_OUTSZ; \
} \
\
- if (sz) { \
- core(r, ctx->a, b); \
- SALSA20_STEP(ctx->a); \
+ if (plan.tail) { \
+ core(r, ctx->a, b); SALSA20_STEP(ctx->a); \
SALSA20_PREPBUF(ctx, b); \
- SALSA20_OUTBUF(ctx, d, s, sz); \
- assert(!sz); \
+ SALSA20_OUTBUF(ctx, d, s, plan.tail); \
} \
}
SALSA20_VARS(DEFENCRYPT)
void XSALSA20_INIT(r, XSALSA20_CTX(r) *ctx, \
const void *key, size_t ksz, const void *nonce) \
{ \
- static const octet zerononce[XSALSA20_NONCESZ]; \
- \
populate(ctx->k, key, ksz); \
ctx->s.a[ 0] = SALSA20_A256; \
ctx->s.a[ 1] = SALSA20_B256; \
typedef struct salsa20_ctx {
salsa20_matrix a;
- octet buf[SALSA20_OUTSZ];
- size_t bufi;
+ octet b[SALSA20_OUTSZ];
+ unsigned off;
} salsa20_ctx;
#define XSALSA20_DEFCTX(name) \
{
uint32 buf[80] = { 0 };
const octet *kk = k;
- uint32 aa = LOAD32(kk);
- uint32 bb = LOAD32(kk + 4);
- uint32 cc = LOAD32(kk + 8);
- uint32 dd = LOAD32(kk + 12);
- uint32 ee = LOAD32(kk + 16);
+ uint32 a, aa = LOAD32(kk);
+ uint32 b, bb = LOAD32(kk + 4);
+ uint32 c, cc = LOAD32(kk + 8);
+ uint32 d, dd = LOAD32(kk + 12);
+ uint32 e, ee = LOAD32(kk + 16);
+
+ unsigned skip = i%5;
+ uint32 x;
+ int j;
- unsigned skip = i % 5;
i /= 5;
/* --- While there's hashing to do, do hashing --- */
while (sz) {
- uint32 a = aa, b = bb, c = cc, d = dd, e = ee;
- int j;
+ a = aa, b = bb, c = cc, d = dd, e = ee;
/* --- Initialize and expand the buffer --- */
buf[0] = i++;
for (j = 16; j < 80; j++) {
- uint32 x = buf[j - 3] ^ buf[j - 8] ^ buf[j - 14] ^ buf[j - 16];
+ x = buf[j - 3] ^ buf[j - 8] ^ buf[j - 14] ^ buf[j - 16];
buf[j] = ROL32(x, 1);
}
/* --- Definitions for round functions --- */
-#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define F(x, y, z) (((x)&(y)) | (~(x)&(z)))
#define G(x, y, z) ((x) ^ (y) ^ (z))
-#define H(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define H(x, y, z) (((x)&(y)) | ((x)&(z)) | ((y)&(z)))
#define T(v, w, x, y, z, i, f, k) do { \
uint32 _x; \
* Since this isn't doing bulk hashing, do it the easy way.
*/
- for (j = 0; j < 20; j++)
- FF(a, b, c, d, e, j);
- for (j = 20; j < 40; j++)
- GG(a, b, c, d, e, j);
- for (j = 40; j < 60; j++)
- HH(a, b, c, d, e, j);
- for (j = 60; j < 80; j++)
- II(a, b, c, d, e, j);
+ for (j = 0; j < 20; j++) FF(a, b, c, d, e, j);
+ for (j = 20; j < 40; j++) GG(a, b, c, d, e, j);
+ for (j = 40; j < 60; j++) HH(a, b, c, d, e, j);
+ for (j = 60; j < 80; j++) II(a, b, c, d, e, j);
/* --- Do the chaining at the end --- */
/* --- Write to the output buffer --- */
switch (skip) {
- case 0:
- if (sz) { *p++ = a; sz--; }
- case 1:
- if (sz) { *p++ = b; sz--; }
- case 2:
- if (sz) { *p++ = c; sz--; }
- case 3:
- if (sz) { *p++ = d; sz--; }
- case 4:
- if (sz) { *p++ = e; sz--; }
- skip = 0;
+ case 0: if (sz) { *p++ = a; sz--; }
+ case 1: if (sz) { *p++ = b; sz--; }
+ case 2: if (sz) { *p++ = c; sz--; }
+ case 3: if (sz) { *p++ = d; sz--; }
+ case 4: if (sz) { *p++ = e; sz--; }
+ skip = 0;
}
}
}
void seal_initkey(seal_key *k, const void *buf, size_t sz)
{
+ sha_ctx h;
+
/* --- Hash the key if it's the wrong size --- */
- if (sz == SHA_HASHSZ)
- memcpy(k->k, buf, sizeof(k->k));
- else {
- sha_ctx c;
- sha_init(&c);
- sha_hash(&c, buf, sz);
- sha_done(&c, k->k);
- }
+ if (sz == SHA_HASHSZ) memcpy(k->k, buf, sizeof(k->k));
+ else { sha_init(&h); sha_hash(&h, buf, sz); sha_done(&h, k->k); }
/* --- Expand the key to fit the various tables --- */
/* --- Ensure that everything is sufficiently diffused --- */
- p = A & 0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9);
- p = B & 0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9);
- p = C & 0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9);
- p = D & 0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9);
- p = A & 0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9);
- p = B & 0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9);
- p = C & 0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9);
- p = D & 0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9);
+ p = A&0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9);
+ p = B&0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9);
+ p = C&0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9);
+ p = D&0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9);
+ p = A&0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9);
+ p = B&0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9);
+ p = C&0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9);
+ p = D&0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9);
/* --- Write out some context --- */
/* --- Diffuse some more --- */
- p = A & 0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9);
- p = B & 0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9);
- p = C & 0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9);
- p = D & 0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9);
+ p = A&0x7fc; B += k->t[p >> 2]; A = ROR32(A, 9);
+ p = B&0x7fc; C += k->t[p >> 2]; B = ROR32(B, 9);
+ p = C&0x7fc; D += k->t[p >> 2]; C = ROR32(C, 9);
+ p = D&0x7fc; A += k->t[p >> 2]; D = ROR32(D, 9);
/* --- Write out the magic numbers --- */
c->l = 0;
c->r = k->r;
c->ri = 0x2000 + SEAL_R;
- c->qsz = 0;
+ c->off = 16;
seal_reset(c);
}
void seal_encrypt(seal_ctx *c, const void *src, void *dest, size_t sz)
{
+ seal_key *k = c->k;
const octet *s = src;
- octet *d = dest;
+ octet *d = dest, *p;
+ uint32 A = c->a, B = c->b, C = c->c, D = c->d;
+ uint32 n1 = c->n1, n2 = c->n2, n3 = c->n3, n4 = c->n4;
+ uint32 aa, bb, cc, dd;
+ unsigned i, j;
+ unsigned P, Q;
/* --- Expect a big dollop of bytes --- */
- if (sz > c->qsz) {
- seal_key *k = c->k;
- uint32 A = c->a, B = c->b, C = c->c, D = c->d;
- uint32 n1 = c->n1, n2 = c->n2, n3 = c->n3, n4 = c->n4;
- uint32 aa, bb, cc, dd;
- unsigned j = c->i;
-
- /* --- Empty the queue first --- */
-
- if (c->qsz) {
- if (d) {
- unsigned i;
- octet *p = c->q + sizeof(c->q) - c->qsz;
- for (i = 0; i < c->qsz; i++)
- *d++ = (s ? *s++ ^ *p++ : *p++);
- }
- sz -= c->qsz;
+ if (sz > 16 - c->off) {
+ j = c->i;
+
+ /* --- Drain the buffer first --- */
+
+ if (c->off < 16) {
+ p = c->buf + c->off; sz -= 16 - c->off;
+ if (!d) /* nothing to do* */;
+ else if (!s) memcpy(d, p, 16 - c->off);
+ else for (i = c->off; i < 16; i++) *d++ = *s++ ^ *p++;
}
/* --- Main sequence --- */
for (;;) {
- unsigned P, Q;
/* --- Reset if we've run out of steam on this iteration --- */
/* --- Make some new numbers --- */
- P = A & 0x7fc; B += k->t[P >> 2]; A = ROR32(A, 9); B ^= A;
- Q = B & 0x7fc; C ^= k->t[Q >> 2]; B = ROR32(B, 9); C += B;
- P = (P + C) & 0x7fc; D += k->t[P >> 2]; C = ROR32(C, 9); D ^= C;
- Q = (Q + D) & 0x7fc; A ^= k->t[Q >> 2]; D = ROR32(D, 9); A += D;
- P = (P + A) & 0x7fc; B ^= k->t[P >> 2]; A = ROR32(A, 9);
- Q = (Q + B) & 0x7fc; C += k->t[Q >> 2]; B = ROR32(B, 9);
- P = (P + C) & 0x7fc; D ^= k->t[P >> 2]; C = ROR32(C, 9);
- Q = (Q + D) & 0x7fc; A += k->t[Q >> 2]; D = ROR32(D, 9);
+ P = A&0x7fc; B += k->t[P >> 2]; A = ROR32(A, 9); B ^= A;
+ Q = B&0x7fc; C ^= k->t[Q >> 2]; B = ROR32(B, 9); C += B;
+ P = (P + C)&0x7fc; D += k->t[P >> 2]; C = ROR32(C, 9); D ^= C;
+ Q = (Q + D)&0x7fc; A ^= k->t[Q >> 2]; D = ROR32(D, 9); A += D;
+ P = (P + A)&0x7fc; B ^= k->t[P >> 2]; A = ROR32(A, 9);
+ Q = (Q + B)&0x7fc; C += k->t[Q >> 2]; B = ROR32(B, 9);
+ P = (P + C)&0x7fc; D ^= k->t[P >> 2]; C = ROR32(C, 9);
+ Q = (Q + D)&0x7fc; A += k->t[Q >> 2]; D = ROR32(D, 9);
/* --- Remember the output and set up the next round --- */
- aa = B + k->s[j + 0];
- bb = C ^ k->s[j + 1];
- cc = D + k->s[j + 2];
- dd = A ^ k->s[j + 3];
+ aa = B + k->s[j + 0]; bb = C ^ k->s[j + 1];
+ cc = D + k->s[j + 2]; dd = A ^ k->s[j + 3];
j += 4;
- if (j & 4)
- A += n1, B += n2, C ^= n1, D ^= n2;
- else
- A += n3, B += n4, C ^= n3, D ^= n4;
+ if (j&4) { A += n1; B += n2; C ^= n1; D ^= n2; }
+ else { A += n3; B += n4; C ^= n3; D ^= n4; }
/* --- Bail out here if we need to do buffering --- */
- if (sz < 16)
- break;
+ if (sz < 16) break;
/* --- Write the next 16 bytes --- */
- if (d) {
+ if (!d) /* nothing to do */;
+ else {
if (s) {
- aa ^= LOAD32_L(s + 0);
- bb ^= LOAD32_L(s + 4);
- cc ^= LOAD32_L(s + 8);
- dd ^= LOAD32_L(s + 12);
+ aa ^= LOAD32_L(s + 0); bb ^= LOAD32_L(s + 4);
+ cc ^= LOAD32_L(s + 8); dd ^= LOAD32_L(s + 12);
s += 16;
}
- STORE32_L(d + 0, aa);
- STORE32_L(d + 4, bb);
- STORE32_L(d + 8, cc);
- STORE32_L(d + 12, dd);
+ STORE32_L(d + 0, aa); STORE32_L(d + 4, bb);
+ STORE32_L(d + 8, cc); STORE32_L(d + 12, dd);
d += 16;
}
sz -= 16;
}
- /* --- Write the new queue --- */
+ /* --- Write the new buffer --- */
- STORE32_L(c->q + 0, aa);
- STORE32_L(c->q + 4, bb);
- STORE32_L(c->q + 8, cc);
- STORE32_L(c->q + 12, dd);
- c->qsz = 16;
+ STORE32_L(c->buf + 0, aa);
+ STORE32_L(c->buf + 4, bb);
+ STORE32_L(c->buf + 8, cc);
+ STORE32_L(c->buf + 12, dd);
+ c->off = 0;
c->a = A; c->b = B; c->c = C; c->d = D;
c->i = j;
}
- /* --- Deal with the rest from the queue --- */
+ /* --- Deal with the rest from the buffer --- */
if (sz) {
- unsigned i;
- octet *p = c->q + sizeof(c->q) - c->qsz;
- if (d) {
- for (i = 0; i < sz; i++)
- *d++ = (s ? *s++ ^ *p++ : *p++);
- }
- c->qsz -= sz;
+ p = c->buf + c->off; c->off += sz;
+ if (!d) /* nothing to do* */;
+ else if (!s) memcpy(d, p, sz);
+ else for (i = 0; i < sz; i++) *d++ = *s++ ^ *p++;
}
}
}
static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)
-{
- gctx *g = (gctx *)c;
- seal_encrypt(&g->cc, s, t, sz);
-}
+ { gctx *g = (gctx *)c; seal_encrypt(&g->cc, s, t, sz); }
static void gsetiv(gcipher *c, const void *iv)
{
}
static void gdestroy(gcipher *c)
-{
- gctx *g = (gctx *)c;
- BURN(*g);
- S_DESTROY(g);
-}
+ { gctx *g = (gctx *)c; BURN(*g); S_DESTROY(g); }
static const gcipher_ops gops = {
&seal,
} grctx;
static void grdestroy(grand *r)
-{
- grctx *g = (grctx *)r;
- BURN(*g);
- S_DESTROY(g);
-}
+ { grctx *g = (grctx *)r; BURN(*g); S_DESTROY(g); }
static int grmisc(grand *r, unsigned op, ...)
{
}
static void grfill(grand *r, void *p, size_t sz)
-{
- grctx *g = (grctx *)r;
- seal_encrypt(&g->cc, 0, p, sz);
-}
+ { grctx *g = (grctx *)r; seal_encrypt(&g->cc, 0, p, sz); }
static const grand_ops grops = {
"seal",
uint32 a, b, c, d; /* Current chaining variables */
uint32 n1, n2, n3, n4; /* Increments for the variables */
unsigned i; /* Index into current iteration */
- octet q[16]; /* Output buffer */
- unsigned qsz; /* Number of bytes in the buffer */
+ octet buf[16]; /* Output buffer */
+ unsigned off; /* Offset into the buffer */
uint32 rbuf[SEAL_R]; /* Buffer for later magic */
} seal_ctx;
#ifndef CATACOMB_@{name:u:c}_H
#define CATACOMB_@{name:u:c}_H
-#ifndef CATACOMB_@{base:u}_H
+#ifndef CATACOMB_@{base:u:c}_H
# include "@base.h"
#endif
f0e1d2c3b4a5968778695a4b3c2d1e0f0011223344556677
fedcba9876543210 05044b62fa52d080;
}
+
+blowfish-cmac {
+ 60d7bcda163547d348b7551195e77022907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268eeee533285a6ed810c9b689daaa906
+ ""
+ 233f464f6f4fed40;
+ 0d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d
+ 1f
+ f80086d1f74c3c25;
+ 337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e
+ 6057acc87638f508046733d9ff61cdbda3b3e9878731ebfe
+ 88141768f1834980;
+ dd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450
+ 727a9b542cde52ebfda19d0ccc520f215eb57b
+ 8b2e3c8554c039c5;
+ b3a4f3ebbbb18ac6c95a97
+ ""
+ 992c2d7bae553fa1;
+ a48030370c33d090c54215
+ ab
+ 3ef759021e0bd2c2;
+ d6b3ad54efc9a38378c5b9
+ 3bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac
+ 7ef83257367f4dcf;
+ 26afa3349829b94586306f
+ ed54154f8f28523c03d4de1600157846b710ee
+ 595b0c57e4ecd664;
+ 72807a2219
+ ""
+ c17ded27f35e843b;
+ bfb474fd71
+ d8
+ 063d632b053cfb61;
+ 91f24bb65d
+ 1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbac
+ aefe8538008cd029;
+ a48b77dba1
+ 89196d1ebba10b0467cb9fc2712a199e533fa9
+ 296073d2f0263834;
+ 156308cdec3f768281e040a9b9a222bd689aef66f5306c
+ ""
+ fc5dcde84c290e8e;
+ eb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb
+ 0b
+ f0e70394d6b143c9;
+ ad7d95214ade49cb3b6f5fe8368131115c037ba323fe1d
+ c8151784873f0eb5b647da6794c18b5337685a96ed65b9ac
+ a9be9c5120820347;
+ a338527ef19b09c063c46f88de9fd41e72d7b97e23e6ea
+ bdff3bcd211499268878dbf30f1dad89d4b9b1
+ a54fb7e239aeec4c;
+}
+
+blowfish-ccm {
+ 60d7bcda163547d348b7551195e77022907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268eeee533285a6ed810c9b689daaa906
+ 0d2d4b
+ ""
+ ""
+ ""
+ c25c474f;
+ 6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f
+ 29549e
+ 6b
+ ""
+ ""
+ 57a5a9c3;
+ 0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638
+ f50804
+ ""
+ 67
+ f4
+ 62383997;
+ 33d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7
+ f65b000961
+ 040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f
+ 215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c5
+ 71ecbda26749ad4076aec1c63db0b7dcec21cf7a4861d69c
+ fb8186360d67254d;
+ 4215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f8f28
+ 523c03d4de
+ 1600157846b710ee72807a2219bfb474fd71d8
+ 91f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbac
+ fa1e4cf72580563be4989ec3530f64fe6b897d54ed59da433615948331
+ 93d5c6d564e86652;
+ a48b77dba189196d1ebba1
+ 0b0467
+ ""
+ ""
+ ""
+ 63379d2c;
+ cb9fc2712a199e533fa915
+ 6308cd
+ ec
+ ""
+ ""
+ 0a7f855f;
+ 3f768281e040a9b9a222bd
+ 689aef
+ ""
+ 66
+ 96
+ d2ba74d4;
+ f5306ceb0c6b08ac8b0a22
+ 260c571b4a
+ 42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe836
+ 8131115c037ba323fe1dc8151784873f0eb5b647da6794c1
+ 458b929afd86f86db6c134400b0d1522882e10660e925b2d
+ 0c69aa29dde98aa1;
+ 8b5337685a96ed65b9aca3
+ 38527ef19b
+ 09c063c46f88de9fd41e72d7b97e23e6eabdff
+ 3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952
+ 5b680782d41f7d46c44d3811c313892f486f1597ed60dc10f15d1c43d5
+ 327a56fa715955fc;
+ d22bb02d71
+ 00b8b6
+ ""
+ ""
+ ""
+ 6eaeedf7;
+ 49377d20a8
+ f08345
+ 5b
+ ""
+ ""
+ eb64c104;
+ 663e4ee131
+ 5f3c8f
+ ""
+ 2a
+ 22
+ 87151792;
+ ebfa921451
+ dcd1af5813
+ b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584
+ b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16
+ 58be2a1ed2225be8ef09f86202a312b01b829eb7e326b926
+ 88f7ac759bdd6989;
+ cb16c2e815
+ f422cdf0c8
+ e30308be3c31e6bc58c0b7cadcb658b970e474
+ 79a684b5aefa69a4cd52147ed12ca986981a874498ad0abef8bc4fcb70
+ 49058d3fde34557441cc9b3e231c87043a5741c3eb99cc2bc58b5f4b6f
+ 87c25970fcee3bba;
+ e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784
+ e0c6f2
+ ""
+ ""
+ ""
+ 16bd95ba;
+ 1195a3b9f4ae985511265febd11c164720eef9eb1c8dd0
+ b00951
+ f2
+ ""
+ ""
+ 44763b0a;
+ 84649016ed00456331854bc78bf43966eb0cfa9138ddc3
+ 990844
+ ""
+ 56
+ b4
+ 8072f963;
+ 08fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d1
+ 26b807e6da
+ a089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973
+ a8cd190107314717a77456f3ff669c732b58db8f48af65f7
+ 86876ace214551f65de8ef07460bc5c70638989bc14365c7
+ 1347b1b46e131d8e;
+ cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b387
+ 66fc69f6a9
+ f2c0945ffd505003cc0cae9ce021a5f1fa4ffa
+ 91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff67785
+ 0f2d12a0832a56f1640d37b17c901d899e2fa4678c867664380cd31062
+ 596d1ddc3b997e5a;
+}
+
+blowfish-eax {
+ 60d7bcda163547d348b7551195e77022907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268eeee533285a6ed810c9b689daaa906
+ ""
+ ""
+ ""
+ ""
+ a6e2fbebaf974200;
+ 0d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d
+ 1f
+ ""
+ ""
+ ""
+ 4cc58c2f4cf91137;
+ 337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e
+ ""
+ 60
+ ""
+ ""
+ c35fc08fda46f599;
+ 57acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb95295
+ ""
+ ""
+ 33
+ 9c
+ b7c0dcb87a8b86c9;
+ 966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030
+ 370c33d090c54215
+ abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb6
+ 48e27fff63102758fe2b69ac26afa3349829b94586306fed
+ 783ab2ee6ea73b63906caf73ceb4376b2e9ebee34fc490c5
+ 3fff7a36718ab82c;
+ 54154f8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df
+ 9fcbaca48b77db
+ a189196d1ebba10b0467cb9fc2712a199e533f
+ a9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac
+ 43bfef92d8c8ba5641fb2523e92ef24d60a41da2e8bb3112aee7b80ce3
+ 07ad2ca904227df7;
+ 8b0a22260c571b4a42bb8f
+ ""
+ ""
+ ""
+ ""
+ bd94df689662060a;
+ db233bfa6a5cfb0bad7d95
+ 21
+ ""
+ ""
+ ""
+ a43ffffe35e1b8a4;
+ 4ade49cb3b6f5fe8368131
+ ""
+ 11
+ ""
+ ""
+ d32da332498a6950;
+ 5c037ba323fe1dc8151784
+ ""
+ ""
+ 87
+ 12
+ 0943c4cb5e3fc7eb;
+ 3f0eb5b647da6794c18b53
+ 37685a96ed65b9ac
+ a338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabd
+ ff3bcd211499268878dbf30f1dad89d4b9b12012e4713df4
+ aebee82a01e138a7229636ee0eb746f6ce13584936f56bb4
+ 5bddd65c9a111ec7;
+ 6795630e7952d22bb02d71
+ 00b8b649377d20
+ a8f083455b663e4ee1315f3c8f2aebfa921451
+ dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584
+ 8a298eafedf8c1e183dfa50569cda59c9f93e56fde173e750e2fa185c7
+ 78a05a55f474688a;
+ b7c5e61766
+ ""
+ ""
+ ""
+ ""
+ 6e8da28b2d84682a;
+ 9c0f16e398
+ 15
+ ""
+ ""
+ ""
+ a6660ae3f78c52b7;
+ d4e9cfce3e
+ ""
+ d1
+ ""
+ ""
+ caa08d52fd0d87cf;
+ ecdf3d264a
+ ""
+ ""
+ 7f
+ b7
+ af92632b8a903cfd;
+ 16cb16c2e8
+ 15f422cdf0c8e303
+ 08be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69
+ a4cd52147ed12ca986981a874498ad0abef8bc4fcb70e27e
+ 773aeb0f1ffbc8b9f0a642275761a79598ab37c4a531e157
+ 7b4483789e1768fc;
+ 98ef1f0446
+ b42fb144d44b6d
+ 00f06dc188d472a784e0c6f21195a3b9f4ae98
+ 5511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331
+ 08d772c882d1d700f980b349e40c3cb563743f62b966fe38ce39831c37
+ 62662279f37c6a9b;
+ 854bc78bf43966eb0cfa9138ddc39908445608fe95e81c
+ ""
+ ""
+ ""
+ ""
+ 99eb415cd27dfb9d;
+ 2533e31c9c1a9851bc2810d858cbbc8424d126b807e6da
+ a0
+ ""
+ ""
+ ""
+ c90ad3bb5ff737a9;
+ 89c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973
+ ""
+ a8
+ ""
+ ""
+ dc32c7a1d4f99131;
+ cd190107314717a77456f3ff669c732b58db8f48af65f7
+ ""
+ ""
+ cc
+ 86
+ 5a32c09bf86a0f69;
+ 9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766
+ fc69f6a9f2c0945f
+ fd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b
+ 9b8f0911e32d65cc1770a18cbfe6effd1ff6778554acf127
+ c9d09215bfda6368733b83186710d656bd900f072a02173d
+ 1e35ed44860e1cb0;
+ 0485b203a3c1c4c967c0a458cb948bdd409b687fa3a682
+ 7b480aa3a4c84c
+ ef64f6c9b53bf8f957f4b03cf43e89957f9a3e
+ 8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf
+ 1b485cb8f21d2744e6fdb19989d90693a8d2b935d0eae05facba546e91
+ 8b86611191b4bdf3;
+}
+
+blowfish-gcm {
+ 60d7bcda163547d348b7551195e77022907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268eeee533285a6ed810c9b689daaa906
+ ""
+ ""
+ ""
+ ""
+ 6b5ff4ee552b5221;
+ 0d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d
+ 1f
+ ""
+ ""
+ ""
+ 88af455e5264ee42;
+ 337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e
+ ""
+ 60
+ ""
+ ""
+ 3349c44a62931118;
+ 57acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb95295
+ ""
+ ""
+ 33
+ 10
+ 0084f273223d1321;
+ 966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030
+ 370c33d090c54215
+ abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb6
+ 48e27fff63102758fe2b69ac26afa3349829b94586306fed
+ e506b433f4b8d79455ba85c9495a93fbdfd6d9b8905ff540
+ 3a7eae4ca30b331e;
+ 54154f8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df
+ 9fcbaca4
+ 8b77dba189196d1ebba10b
+ 0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5
+ 300fa70b6ef7bfd848bb6686af20bd3fdd3c24870e4b3e27ebe638a6574f74666b
+ 3c7cd92967f27b1b;
+ 306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f
+ 0eb5b647da6794
+ c18b5337685a96ed65b9aca338527ef19b09c0
+ 63c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1d
+ 5a4f347d4d422000d0df51f4cb24b0be321466d6730f7a811e36dc030c
+ 15585b78049dd4fe;
+ ad89d4b9b12012e4713df4
+ ""
+ ""
+ ""
+ ""
+ fe363b1f2ccd1251;
+ 6795630e7952d22bb02d71
+ 00
+ ""
+ ""
+ ""
+ 9b93dde4b132c750;
+ b8b649377d20a8f083455b
+ ""
+ 66
+ ""
+ ""
+ bbc2c3a8d6d3ee89;
+ 3e4ee1315f3c8f2aebfa92
+ ""
+ ""
+ 14
+ e6
+ 66a62c95caa9cbfb;
+ 51dcd1af5813b70d30ce2f
+ 1fef6ef315d07983
+ 91805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9
+ cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308
+ 2f5da54ea8b3beafd0f3dd6ac4e10650dd2ed421f8ce5ec1
+ 9ce22826bbc14984;
+ be3c31e6bc58c0b7cadcb6
+ 58b970e4
+ 7479a684b5aefa69a4cd52
+ 147ed12ca986981a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b6d
+ e1b7effaaf9fd5e129cfc598bc26a0100ea9bac25c51aeabb75a7127e05c1bc9bc
+ ae765f924e885d78;
+ 00f06dc188d472a784e0c6
+ f21195a3b9f4ae
+ 985511265febd11c164720eef9eb1c8dd0b009
+ 51f284649016ed00456331854bc78bf43966eb0cfa9138ddc399084456
+ 6bc0e656e9939d5fe58ad77acbcec603f5111cbe660d6b62d1c241ba6c
+ 47b8a5c7cd546e34;
+ 08fe95e81c
+ ""
+ ""
+ ""
+ ""
+ 70b8e6f27adb97d9;
+ 2533e31c9c
+ 1a
+ ""
+ ""
+ ""
+ f334ea3a3b8ec059;
+ 9851bc2810
+ ""
+ d8
+ ""
+ ""
+ 802c25c30e3c0441;
+ 58cbbc8424
+ ""
+ ""
+ d1
+ 79
+ 74d9b3cdc4ce7003;
+ 26b807e6da
+ a089c3f9099c5ffb
+ 824173d7634c04226f30cbb7f0e4a973a8cd190107314717
+ a77456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b7
+ f9e5d38f1d9ce21dc3b940af936de5b80b4ac4b034adb539
+ 33d122be105fb43e;
+ 30374ffc9b
+ c597f56c
+ cbb2f294b38766fc69f6a9
+ f2c0945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e3
+ 9895b89d611def800949f45f4e61129a3722df9b15f37afca829d4fc08266acf57
+ 7ac2cc22e1d5568d;
+ 2d65cc1770
+ a18cbfe6effd1f
+ f6778554acf1270485b203a3c1c4c967c0a458
+ cb948bdd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957f4b0
+ bb5e83aa69b5356dceec0fe74656f2e4399e12c85e09dd2f8fb609c72a
+ 2b642aa6511caace;
+ 3cf43e89957f9a3e8128f8743d16687b7bb8deb9bd205b
+ ""
+ ""
+ ""
+ ""
+ 991808a4cd53e573;
+ 70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac84
+ 51
+ ""
+ ""
+ ""
+ 12bc329cc3ff10a9;
+ 399587011677508a15dde524af3e2bee0646541a42c2ec
+ ""
+ cc
+ ""
+ ""
+ 7ebd5d67b3fed4e4;
+ b44d65bad397abfaf529ee41cf9a05c7efedef3401539c
+ ""
+ ""
+ 51
+ 1e
+ 6b6575eab9424e98;
+ d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a
+ 5718fd25014107c8
+ e7d715a92add9589d1f5c054b2d983514605ec590294a319
+ b9802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70
+ 4c86b78d99617ef3a0e2ba3306379b71221b44b4f53f5526
+ 7cb8282ea97b3894;
+ d17d4569eaff59a332ba58d5d5589bfe079753ee1a957e
+ b6d6699e
+ 6b7ea2725cb2dac07ecde9
+ 5759ac46fee6dda7abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9
+ 9001bbc3c0a5c6447968b8eec61f2e49ca7129b0560ea49201d997d682bc36984f
+ 0c14462ce512a43d;
+ cf44bbc8c6254d980398bd94e66eb4563d405e51881e99
+ 027b8ab9aea3cc
+ f860b0009740763d96836c5f87b95460938de1
+ 288c69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7
+ 3bf9da6973a8dc56cebcb99962a74dc8638d11f4cb1d932162cd63136e
+ ff4072c9c5180f17;
+}
+
+blowfish-ocb1 {
+ 60d7bcda163547d348b7551195e77022907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268eeee533285a6ed810c9b689daaa906
+ 0d2d4b6003062365
+ ""
+ ""
+ ""
+ 5f3f51e08130263d;
+ b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d
+ 27a4ba234085406a
+ 61
+ ""
+ ""
+ 8de51300e0d17d9d;
+ 36512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbd
+ a3b3e9878731ebfe
+ ""
+ dd
+ 11
+ 1baa12d5cdfeeee5;
+ 4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa45072
+ 7a9b542cde52ebfd
+ ""
+ a19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030
+ c1901311bcbe5d48115af605ce28802572f30dff577e27ec
+ 330d726cadffef1c;
+ 370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26afa3349829b94586306f
+ ed54154f8f28523c
+ 03d4de1600157846b710ee72807a2219bfb474fd71d891f2
+ 4bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df
+ 0a2dd79bb802baad38fb7e60e979c30bbbbcae5e5bfe515d
+ 0ee0e2a8987f11b4;
+ 9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac
+ 8b0a22260c571b4a
+ ""
+ 42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c03
+ 0f42a8f34bf068232057195d449b9414f3bb33a692bff50f90f86b2d83
+ 6cfb2c8b4b3ac1f8;
+ 7ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3b
+ cd211499268878db
+ f30f1dad89d4b9b12012e4713df46795630e79
+ 52d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa
+ eda7fb91f70e24d3ac9751e7132f6b104e41392dac28bf4f0e5daaa2b6
+ 04f7c455e5d023ab;
+ 921451dcd1af5813b70d30
+ ce2f1fef6ef315d0
+ ""
+ ""
+ ""
+ 4a33cb478b8f393b;
+ 798391805da08da3aefc5f
+ 8584b7c5e617669c
+ 0f
+ ""
+ ""
+ 8745d6a0c38b7bb0;
+ 16e39815d4e9cfce3ed1ec
+ df3d264a7f16cb16
+ ""
+ c2
+ 3c
+ 20ab4fe539c6b1ef;
+ e815f422cdf0c8e30308be
+ 3c31e6bc58c0b7ca
+ ""
+ dcb658b970e47479a684b5aefa69a4cd52147ed12ca98698
+ bc0a5d98e5825c5e804c67213a1d820e29ef7dfddab70a5f
+ 40854bd91c065d0d;
+ 1a874498ad0abef8bc4fcb
+ 70e27e98ef1f0446
+ b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4
+ ae985511265febd11c164720eef9eb1c8dd0b00951f28464
+ 1a2ad5ef98fce431c6e9e85fdd057e59d2954f8e96bbadc8
+ 979de99c867f2951;
+ 9016ed00456331854bc78b
+ f43966eb0cfa9138
+ ""
+ ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d1
+ 78687a94824bb12dfe6e650544f042524ead2780a8bb4dde09d3621ec4
+ d8dd93d379eb140f;
+ 26b807e6daa089c3f9099c
+ 5ffb824173d7634c
+ 04226f30cbb7f0e4a973a8cd190107314717a7
+ 7456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc5
+ b58e5fed2f88013418795c660e6e4b5ae3262382a534d79656c02a42f1
+ 7391763bfa5e91d1;
+ 97f56ccbb2
+ f294b38766fc69f6
+ ""
+ ""
+ ""
+ de47841b0e181038;
+ a9f2c0945f
+ fd505003cc0cae9c
+ e0
+ ""
+ ""
+ 9e1855698acdf3f7;
+ 21a5f1fa4f
+ fa91544485f1a125
+ ""
+ 8b
+ 46
+ 279f95fd345d8d07;
+ 2b9b8f0911
+ e32d65cc1770a18c
+ ""
+ bfe6effd1ff6778554acf1270485b203a3c1c4c967c0a458
+ 6abecbf72aed482a6f80d57b236c40d316e20362f5561ff6
+ cc8e958357592f6f;
+ cb948bdd40
+ 9b687fa3a6827b48
+ 0aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a3e
+ 8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9
+ 322b60b89783b356ffcddc812e11459c1841d1540a91057d
+ 48feb980547cfd06;
+ e9a79b1abf
+ 91b0851e5ca605ac
+ ""
+ 8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65
+ 735b81e7bf11cb6e02de6657d638e735c41336f7d021d1e6b07c8aaa69
+ f21aba6b029d81a5;
+ bad397abfa
+ f529ee41cf9a05c7
+ efedef3401539c51d2a90bbf7f1bfc338ab0ef
+ 5746ea8fdcccd213e33f7e8a5718fd25014107c8e7d715a92add9589d1
+ 094621285cf10b55b5c7ac0287f2267a8b4f9fecdd2e4107a88c16bd91
+ 0a2c24953366e55d;
+ f5c054b2d983514605ec590294a319b9802068a9f891bc
+ 5ba5afabf8c3122d
+ ""
+ ""
+ ""
+ c9a161d460c36f70;
+ 12d7ff3c41122d70d17d4569eaff59a332ba58d5d5589b
+ fe079753ee1a957e
+ b6
+ ""
+ ""
+ 60dd373e888b983a;
+ d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7ab
+ c8ad68daac90cfe2
+ ""
+ 2d
+ 34
+ f2b20b2e78622af4;
+ 2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d98
+ 0398bd94e66eb456
+ ""
+ 3d405e51881e99027b8ab9aea3ccf860b0009740763d9683
+ 1d2773587c73b701d3cc8beb604ce8f285046e6879e5c0e5
+ ba34965f7a472a8f;
+ 6c5f87b95460938de1288c69d80ea12ff4bb5f069b8a2e
+ 86041c1b9fc214e9
+ ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c
+ 36800d9645563a308ba60076817523bd2abf1261b089d8f2
+ b0d06d7557017e3cd08c88a3a3d744ec0d7d964e72197911
+ 9de86854fdf00689;
+ 3a9c2835076a23faac2cdd67771cc667a8331f0a170b66
+ 283e4f834a06148f
+ ""
+ 302c3973accd56f6f24e33958b8c2e2352fd61e4fa8fec816ac861a8b3
+ f91ee277a3c2b93ce6c8df23263fd829225d66ff7f8bba9612230e8bf1
+ d2c7d587cbddcddd;
+ 3779f09e7a10fc02a8f48afa3080ee119a52a9a817e4f2
+ b94b0820cab383a8
+ cffeea7c486315799dc875fba578c8ec483789
+ 8a92142b5b0677da1ac273117b45bcfff5d5f8b6fde2893232a9f81d14
+ 00e25b2c5fdee0b87cd2c66474f852256a4e3b6239ef6ba512af0f74c0
+ 5711f23d4b34df7f;
+}
+
+blowfish-pmac1 {
+ 60d7bcda163547d348b7551195e77022907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268eeee533285a6ed810c9b689daaa906
+ ""
+ db56f7585ef1b3ea;
+ 0d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d
+ 1f
+ fe51530be20f5059;
+ 337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e
+ 6057acc87638f508046733d9ff61cdbda3b3e9878731ebfe
+ 370a72ba02c69145;
+ dd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450
+ 727a9b542cde52ebfda19d0ccc520f215eb57b
+ b31c99831d7ad455;
+ b3a4f3ebbbb18ac6c95a97
+ ""
+ 41939f3db560fdb4;
+ a48030370c33d090c54215
+ ab
+ d56476908d8efe7a;
+ d6b3ad54efc9a38378c5b9
+ 3bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac
+ 7f864cbc1bee3343;
+ 26afa3349829b94586306f
+ ed54154f8f28523c03d4de1600157846b710ee
+ a344715c78dc0063;
+ 72807a2219
+ ""
+ 78e276b95d095a71;
+ bfb474fd71
+ d8
+ 9b5c25004d486060;
+ 91f24bb65d
+ 1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbac
+ 1d4dbe26bc70c6bc;
+ a48b77dba1
+ 89196d1ebba10b0467cb9fc2712a199e533fa9
+ 3b97fb336799efbd;
+ 156308cdec3f768281e040a9b9a222bd689aef66f5306c
+ ""
+ cc20b90115cd712c;
+ eb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb
+ 0b
+ eb75059c3f5ccc65;
+ ad7d95214ade49cb3b6f5fe8368131115c037ba323fe1d
+ c8151784873f0eb5b647da6794c18b5337685a96ed65b9ac
+ f0576e12bc1af195;
+ a338527ef19b09c063c46f88de9fd41e72d7b97e23e6ea
+ bdff3bcd211499268878dbf30f1dad89d4b9b1
+ e193575442a800ab;
+}
+
+blowfish-ocb3 {
+ 60d7bcda163547d348b7551195e77022907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268eeee533285a6ed810c9b689daaa906
+ 0d2d4b600306
+ ""
+ ""
+ ""
+ b3583d3de56211f4;
+ 2365b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e
+ 6b0d27a4ba23
+ 40
+ ""
+ ""
+ 912c60b4f34b6731;
+ 85406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9
+ ff61cdbda3b3
+ ""
+ e9
+ dd
+ 49ef753d0e5893dc;
+ 878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9
+ b2fc5f
+ ""
+ a450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3
+ 104cef2c140c06f2a9c502bd63c02be3d940a76e94b52e8e
+ 2279d2765293b605;
+ ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac
+ 26afa33498
+ 29b94586306fed54154f8f28523c03d4de1600157846b710
+ ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b
+ e2f8d8fe5551cca9b88351ee9e422ceb2ed4abfaca8fa2b8
+ 4cce00e139bd21d6;
+ 571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a2
+ 22bd689aef66
+ ""
+ f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d
+ e4fddb14c2c34d5695f13bdc9e21f6ff4605c864e2e7b0550606d5f478
+ c07b9776137a4225;
+ 95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c4
+ 6f88de9fd41e
+ 72d7b97e23e6eabdff3bcd211499268878dbf3
+ 0f1dad89d4b9b12012e4713df46795630e7952d22bb02d7100b8b64937
+ c64055e9e272881679259cd8f6d67f2291cea67a6865f4af686f02f032
+ 32eace6f457de00d;
+ 7d20a8f083455b663e4ee1
+ 315f3c8f2aeb
+ ""
+ ""
+ ""
+ 99933637fa8f2b85;
+ fa921451dcd1af5813b70d
+ 30ce2f1fef6e
+ f3
+ ""
+ ""
+ b6e8c9c6a45b2a56;
+ 15d0798391805da08da3ae
+ fc5f8584b7c5
+ ""
+ e6
+ 80
+ 3facc6b40f6e5187;
+ 17669c0f16e39815d4e9cf
+ ce3ed1
+ ""
+ ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6
+ 859387df0c8d6efe243bba8c894f17fa1935f42cd6148235
+ 4d1dd56b61f0988b;
+ bc58c0b7cadcb658b970e4
+ 7479a684b5
+ aefa69a4cd52147ed12ca986981a874498ad0abef8bc4fcb
+ 70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784
+ ebf8c0ff4e24b5754891cff817c499efa87b8a9fdf0d2cc1
+ 1d3775fe8dc794e7;
+ e0c6f21195a3b9f4ae9855
+ 11265febd11c
+ ""
+ 164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966
+ cc19d5c325f9e65a669dc5e47d9ebfc15d3a3f609d8a96bf9d6eb710fa
+ dba9d363c65b7e0b;
+ eb0cfa9138ddc399084456
+ 08fe95e81c25
+ 33e31c9c1a9851bc2810d858cbbc8424d126b8
+ 07e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd
+ 53fd73e769e423e95ea852b9f025096cff34e3d1902ff701cdf24790c8
+ eb3ca419114e51fe;
+ 1901073147
+ 17a77456f3ff
+ ""
+ ""
+ ""
+ be3a587aad834d02;
+ 669c732b58
+ db8f48af65f7
+ cc
+ ""
+ ""
+ 2d749c7591283c5c;
+ 9e3fb90e17
+ 21b730374ffc
+ ""
+ 9b
+ 43
+ 0e0346447f445eca;
+ c597f56ccb
+ b2f294
+ ""
+ b38766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa
+ 06da8393393846121625c231930a8490f2a4ce8b89447e2b
+ 78e64ea8e4df5f24;
+ 4ffa915444
+ 85f1a1258b
+ 2b9b8f0911e32d65cc1770a18cbfe6effd1ff6778554acf1
+ 270485b203a3c1c4c967c0a458cb948bdd409b687fa3a682
+ 8f7152ef08106003140fd22ae1d7911123b04337f8e2cff6
+ c3c1d8284b448b74;
+ 7b480aa3a4
+ c84cef64f6c9
+ ""
+ b53bf8f957f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd20
+ d0d64b53c566f1dc431a72dda89c51a7b7d25a57638af924b7f56d75e7
+ c691e0e094254334;
+ 5b70e04c09
+ 1d205cdad9e9
+ a79b1abf91b0851e5ca605ac84513995870116
+ 77508a15dde524af3e2bee0646541a42c2ecccb44d65bad397abfaf529
+ b930562d3cc00abaeaa1dc8ff5825cdf086e0ba72916c06d9bd4f837bd
+ 90343080f7fb1dda;
+ ee41cf9a05c7efedef3401539c51d2a90bbf7f1bfc338a
+ b0ef5746ea8f
+ ""
+ ""
+ ""
+ 91f6852537252f8a;
+ dcccd213e33f7e8a5718fd25014107c8e7d715a92add95
+ 89d1f5c054b2
+ d9
+ ""
+ ""
+ b36663b6367ef6ef;
+ 83514605ec590294a319b9802068a9f891bc5ba5afabf8
+ c3122d12d7ff
+ ""
+ 3c
+ e5
+ 1961c689d2d77714;
+ 41122d70d17d4569eaff59a332ba58d5d5589bfe079753
+ ee1a95
+ ""
+ 7eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7
+ cb0853f95fc84b810db7f3b9518d6c1a1ef5e78a3d316746
+ 5b65e59ea9a723f0;
+ abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb35
+ 42a9cf44bb
+ c8c6254d980398bd94e66eb4563d405e51881e99027b8ab9
+ aea3ccf860b0009740763d96836c5f87b95460938de1288c
+ fbd80f2a162c319b91c99ed4a0f8860cbad42c59792cf7ac
+ 35dac492225424a6;
+ 69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186
+ ddf1f6a7a3aa
+ ""
+ 7e740da967828e3604b35b15ffaa6c36800d9645563a308ba600768175
+ 75bef1ae59a3404b09299f06461e0cbb3a9d6e58d4f49928f9b0845f01
+ f93d21e578e90e18;
+ 23bd2abf1261b089d8f23a9c2835076a23faac2cdd6777
+ 1cc667a8331f
+ 0a170b66283e4f834a06148f302c3973accd56
+ f6f24e33958b8c2e2352fd61e4fa8fec816ac861a8b33779f09e7a10fc
+ 6128d1bdba407d841d26fb849b2f1967f1877822a75c402b845bd5f1b1
+ 2951dd60e7a50fe4;
+}
+
+blowfish-ocb3-mct {
+ 56 1eaefdb48ac7e8be;
+ 52 b79553ab012d6259;
+ 48 e596561501cbb1d1;
+ 44 0b3d0dd4007cc8e1;
+ 40 5e01c4481579151f;
+ 36 f745536adb730368;
+ 32 261481ed1915729e;
+ 28 b6fa034db1ed80e8;
+ 24 0b7aed4db823ce0c;
+ 20 472a7cbbc3b93999;
+ 16 4434cb1c40f21097;
+ 12 4f64439b9bcedfc2;
+ 10 654a7c2699f7e4db;
+ 8 b0d1574724b61c02;
+ 56 883bad05122a;
+ 52 1cf7ba9a0e86;
+ 48 44d9c92bfb48;
+ 44 2ab05efeab38;
+ 40 fb1788302233;
+ 36 926b61ed2153;
+ 32 d240e2d8b6e9;
+ 28 6a7452bc8c50;
+ 24 7be498392971;
+ 20 90d3cb1c76c2;
+ 16 a4ce66e48d8f;
+ 12 15a879e95625;
+ 10 2af8e886f690;
+ 8 c3ecbf857159;
+ 56 f196b27c;
+ 52 84c6f8e6;
+ 48 2323c6f4;
+ 44 c3c03f9d;
+ 40 57979457;
+ 36 318c4335;
+ 32 1928bd41;
+ 28 cb2429ec;
+ 24 369cdefd;
+ 20 45e7c011;
+ 16 32768164;
+ 12 469cab17;
+ 10 17a3dd1d;
+ 8 a4a15a19;
+}
0123456789abcdef
7ac816d16e9b302e;
}
+
+cast128-cmac {
+ 60d7bcda163547d348b7551195
+ ""
+ e027f02068e914e0;
+ e77022907dd1dff7dac5c9941d
+ 26
+ a28361e0bd2c591c;
+ d0c6eb14ad568f86edd1dc9268
+ eeee533285a6ed810c9b689daaa9060d2d4b6003062365b0
+ 4eeb71793dd20683;
+ a54364c76c160f11896c479484
+ 6ecfa14a7130c9f137120634c9519848a877ff
+ f46b0adba4856f4f;
+ 77bf79192a5b50
+ ""
+ 79360635503a7f04;
+ ade5d9cd739a3d
+ 1f
+ 9a100ee7cd214433;
+ 337f29549e6b0d
+ 27a4ba234085406a6136512061f7080cc07df0591d8fa21f
+ 81e6063cc8dd3e25;
+ 2dd88374d8cde8
+ e160ad10997a21635c6d62c9269029df3e6057
+ 077ce3be2b167375;
+ acc87638f508046733d9
+ ""
+ e0ac1c1c71776fcb;
+ ff61cdbda3b3e9878731
+ eb
+ de618ec3a0d64ca2;
+ fedd4705e505da1435dc
+ eaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533
+ 1b5ed15a16456292;
+ 966f27043eb621b7f65b
+ 000961040ef2f9b2fc5fa450727a9b542cde52
+ fe228a47df7c250d;
+ ebfda19d0ccc520f21
+ ""
+ e8d3cb82a354843c;
+ 5eb57bb3a4f3ebbbb1
+ 8a
+ c7fcbad7ee9257d3;
+ c6c95a97a48030370c
+ 33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad260
+ 1d547d096465faf6;
+ 5faee2b03fb648e27f
+ ff63102758fe2b69ac26afa3349829b9458630
+ 10bd2c18c3337a4f;
+}
+
+cast128-ccm {
+ 60d7bcda163547d348b7551195
+ e77022
+ ""
+ ""
+ ""
+ 4905fdcf;
+ 907dd1dff7dac5c9941d26d0c6
+ eb14ad
+ 56
+ ""
+ ""
+ 327786b3;
+ 8f86edd1dc9268eeee533285a6
+ ed810c
+ ""
+ 9b
+ 7d
+ 9d869519;
+ 689daaa9060d2d4b6003062365
+ b0a54364c7
+ 6c160f11896c4794846ecfa14a7130c9f137120634c95198
+ 48a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e
+ c935111d2f5913c3a992e7b11d538a1f5750237258739dd7
+ ccae7a45efc12caf;
+ 6b0d27a4ba234085406a613651
+ 2061f7080c
+ c07df0591d8fa21f2dd88374d8cde8e160ad10
+ 997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbd
+ 9bd2a0c0f027a5a1b56974b85be03dd3ffe81b5f2a2381170fb7eca747
+ 711646ef1dde6cad;
+ a3b3e9878731eb
+ fedd47
+ ""
+ ""
+ ""
+ af3e6347;
+ 05e505da1435dc
+ eaa7b1
+ cc
+ ""
+ ""
+ 571ec017;
+ 49ae1d50c38201
+ a89447
+ ""
+ 6b
+ 1b
+ 1859fcd4;
+ 3f102b752eb952
+ 9533966f27
+ 043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542c
+ de52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a
+ 63f409a8d0dba1ec4c090efd260b557d0359482f69d62126
+ 7d4b85fb7d13bf0c;
+ 97a48030370c33
+ d090c54215
+ abd6b3ad54efc9a38378c5b93bf4f2aad2605f
+ aee2b03fb648e27fff63102758fe2b69ac26afa3349829b94586306fed
+ 018425effd80fbb802f204bdefb41d4b2fa140dd2b2149580b72428bab
+ 53bd8b75c9a3bc09;
+ 54154f8f28523c03d4de
+ 160015
+ ""
+ ""
+ ""
+ 4397bfc8;
+ 7846b710ee72807a2219
+ bfb474
+ fd
+ ""
+ ""
+ a28f8e1e;
+ 71d891f24bb65d156325
+ 9f9eb5
+ ""
+ 3b
+ cf
+ 185c4f64;
+ 571ea629c54d57dd2d42
+ f70800df9f
+ cbaca48b77dba189196d1ebba10b0467cb9fc2712a199e53
+ 3fa9156308cdec3f768281e040a9b9a222bd689aef66f530
+ 030e417475032f357c1257444a95486a4e0e652beb78ee50
+ a36e60d6e4fffa0d;
+ 6ceb0c6b08ac8b0a2226
+ 0c571b4a42
+ bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b
+ 6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b
+ ae6c8d1d32a0ecff25eb9c81ff41dc0f31a9e9df6d96d7aa499a001ad1
+ cad9b682638f7a11;
+ 5337685a96ed65b9ac
+ a33852
+ ""
+ ""
+ ""
+ cee2fb45;
+ 7ef19b09c063c46f88
+ de9fd4
+ 1e
+ ""
+ ""
+ f82a2ce3;
+ 72d7b97e23e6eabdff
+ 3bcd21
+ ""
+ 14
+ 8e
+ cf442fcb;
+ 99268878dbf30f1dad
+ 89d4b9b120
+ 12e4713df46795630e7952d22bb02d7100b8b649377d20a8
+ f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b7
+ d3216e8ddc4bae39da814c7541496567ad7669f3ebfafba7
+ ffef801deb5ef8fd;
+ 0d30ce2f1fef6ef315
+ d079839180
+ 5da08da3aefc5f8584b7c5e617669c0f16e398
+ 15d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c
+ d9f3345b6b1782cd1db09c53d2076a2b84f4cc16e94c58cb46cbd5d85e
+ c46139beb639552b;
+}
+
+cast128-eax {
+ 60d7bcda163547d348b7551195
+ ""
+ ""
+ ""
+ ""
+ de756459eefbe735;
+ e77022907dd1dff7dac5c9941d
+ 26
+ ""
+ ""
+ ""
+ 706c2756289404eb;
+ d0c6eb14ad568f86edd1dc9268
+ ""
+ ee
+ ""
+ ""
+ 1dba9d384981a899;
+ ee533285a6ed810c9b689daaa9
+ ""
+ ""
+ 06
+ 9c
+ e1c1cb285fe6fd42;
+ 0d2d4b6003062365b0a54364c7
+ 6c160f11896c4794
+ 846ecfa14a7130c9f137120634c9519848a877ff77bf7919
+ 2a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085
+ 7ea32c98c18f380ebf49a8153a036aba80fc8219ee85ea9a
+ 678b76a28d6415ac;
+ 406a6136512061f7080cc07df0
+ 591d8fa21f2dd8
+ 8374d8cde8e160ad10997a21635c6d62c92690
+ 29df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd47
+ 21ed0355fd3256ebee4847ec0d0f6a024e6ea0f2cd8a5de1f5bb139385
+ d4a1d384f6234b97;
+ 05e505da1435dc
+ ""
+ ""
+ ""
+ ""
+ cbbb9ef570741e49;
+ eaa7b1cc49ae1d
+ 50
+ ""
+ ""
+ ""
+ f8c34e199b130f87;
+ c38201a894476b
+ ""
+ 3f
+ ""
+ ""
+ 76bfe7342f08a0d9;
+ 102b752eb95295
+ ""
+ ""
+ 33
+ 40
+ 78d8ced34fba2669;
+ 966f27043eb621
+ b7f65b000961040e
+ f2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215e
+ b57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215
+ 2ab0a37f0ebd0523111d8079b33285016f8038eb01d8c726
+ 2557d7fde2b5cbf4;
+ abd6b3ad54efc9
+ a38378c5b93bf4
+ f2aad2605faee2b03fb648e27fff63102758fe
+ 2b69ac26afa3349829b94586306fed54154f8f28523c03d4de16001578
+ cde7aba02b6c423e5a4c5bee6592a8c6beedd60b458982ecb96ec2d05a
+ 4b957468a1b84eaf;
+ 46b710ee72807a2219bf
+ ""
+ ""
+ ""
+ ""
+ 4c34faee63cc6ded;
+ b474fd71d891f24bb65d
+ 15
+ ""
+ ""
+ ""
+ fe3d9bc8bb1fadc7;
+ 63259f9eb53b571ea629
+ ""
+ c5
+ ""
+ ""
+ 89349e8fa6362b16;
+ 4d57dd2d42f70800df9f
+ ""
+ ""
+ cb
+ f0
+ 3f45042252ade21c;
+ aca48b77dba189196d1e
+ bba10b0467cb9fc2
+ 712a199e533fa9156308cdec3f768281e040a9b9a222bd68
+ 9aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb23
+ b5c79faaecf9c2d65703aae2c578b606b455c25f6aec3a4b
+ fe3a14a18c793f8d;
+ 3bfa6a5cfb0bad7d9521
+ 4ade49cb3b6f5f
+ e8368131115c037ba323fe1dc8151784873f0e
+ b5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c46f88
+ b8d413238c76153b01f0a2823e24414f91988638bf3a80cdb6a211700f
+ 12e4967ff0500b9f;
+ de9fd41e72d7b97e23
+ ""
+ ""
+ ""
+ ""
+ caab65ebca9b09cd;
+ e6eabdff3bcd211499
+ 26
+ ""
+ ""
+ ""
+ 7fb3ef6dc33a52ea;
+ 8878dbf30f1dad89d4
+ ""
+ b9
+ ""
+ ""
+ 1781664543c4675f;
+ b12012e4713df46795
+ ""
+ ""
+ 63
+ 41
+ 9d8c48bc137b207a;
+ 0e7952d22bb02d7100
+ b8b649377d20a8f0
+ 83455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d
+ 30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5
+ bf81b5c1007332ff360b167545ff826c131e6279a40ec6f3
+ e037dbce43a14ff2;
+ e617669c0f16e39815
+ d4e9cfce3ed1ec
+ df3d264a7f16cb16c2e815f422cdf0c8e30308
+ be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed1
+ 9b3b606592501407cf47aa56b3136cca02d94d282ebf6d5f441b32b9f3
+ d8a34c6cae422b2c;
+}
+
+cast128-gcm {
+ 60d7bcda163547d348b7551195
+ ""
+ ""
+ ""
+ ""
+ 827e37433b2c1494;
+ e77022907dd1dff7dac5c9941d
+ 26
+ ""
+ ""
+ ""
+ 603a0e329e3029ed;
+ d0c6eb14ad568f86edd1dc9268
+ ""
+ ee
+ ""
+ ""
+ 09e36329c9190d21;
+ ee533285a6ed810c9b689daaa9
+ ""
+ ""
+ 06
+ 0b
+ 83b106e61ac95294;
+ 0d2d4b6003062365b0a54364c7
+ 6c160f11896c4794
+ 846ecfa14a7130c9f137120634c9519848a877ff77bf7919
+ 2a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085
+ d83412ab72752e456aba4b235ea84e65d99a082caea1eba5
+ 9ded1889068ab798;
+ 406a6136512061f7080cc07df0
+ 591d8fa2
+ 1f2dd88374d8cde8e160ad
+ 10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9
+ b0f1bd0e10c71ddab6c3c3a1b5cb5e0cf831042e831b12789ac9d617e21e573dac
+ 8a619f19a69e0bff;
+ 878731ebfedd4705e505da1435
+ dceaa7b1cc49ae
+ 1d50c38201a894476b3f102b752eb952953396
+ 6f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52eb
+ fa5b4ee08950d597fcb0affdf0f0aa8174ca0e9dcfc4ee13e4b5a2bae1
+ b6ce5f7d53e6177b;
+ fda19d0ccc520f
+ ""
+ ""
+ ""
+ ""
+ 522de0429e89383a;
+ 215eb57bb3a4f3
+ eb
+ ""
+ ""
+ ""
+ 45fb1e234c4d8ccd;
+ bbb18ac6c95a97
+ ""
+ a4
+ ""
+ ""
+ 89dab6195164787c;
+ 8030370c33d090
+ ""
+ ""
+ c5
+ bd
+ 870b563762624fec;
+ 4215abd6b3ad54
+ efc9a38378c5b93b
+ f4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26
+ afa3349829b94586306fed54154f8f28523c03d4de160015
+ 3cbe2ea8aa7c3ea77e46a9afbd7f69fc51f663820293720c
+ ff1dcf81a83ea960;
+ 7846b710ee7280
+ 7a2219bf
+ b474fd71d891f24bb65d15
+ 63259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebb
+ f54b9538cef3257defa694754b7e196a132d042c670e72a1dcb527f660b836f098
+ 59f1ff473e5232e6;
+ a10b0467cb9fc2
+ 712a199e533fa9
+ 156308cdec3f768281e040a9b9a222bd689aef
+ 66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad
+ f8432f79ab5a3e07c7dff91e912d79f7e6b6828b8a10c74bf419d9448f
+ 0ec34f0d7a1b4c11;
+ 7d95214ade49cb3b6f5f
+ ""
+ ""
+ ""
+ ""
+ 08185a4aee37b676;
+ e8368131115c037ba323
+ fe
+ ""
+ ""
+ ""
+ 14a6486a55038a65;
+ 1dc8151784873f0eb5b6
+ ""
+ 47
+ ""
+ ""
+ 598e10f99a3c9a58;
+ da6794c18b5337685a96
+ ""
+ ""
+ ed
+ 39
+ fd918834389b1469;
+ 65b9aca338527ef19b09
+ c063c46f88de9fd4
+ 1e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89
+ d4b9b12012e4713df46795630e7952d22bb02d7100b8b649
+ 1c3d067c765e17b338cf91585a0caf2f70bc663db8274944
+ 09ab5e3cd3740b16;
+ 377d20a8f083455b663e
+ 4ee1315f
+ 3c8f2aebfa921451dcd1af
+ 5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f
+ 4b8874ad4cb500f61ff68c73c68dda4f440ad538ded72c0d5a265ce5721cf354f9
+ 77bda550c71cc140;
+ 16e39815d4e9cfce3ed1
+ ecdf3d264a7f16
+ cb16c2e815f422cdf0c8e30308be3c31e6bc58
+ c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a87
+ fba726477f0a66ba98a278b52e721b41ebb36556e59d2e9830e66fe0a1
+ 9666883d3ef07a79;
+ 4498ad0abef8bc4fcb
+ ""
+ ""
+ ""
+ ""
+ 4417c135917f0b7e;
+ 70e27e98ef1f0446b4
+ 2f
+ ""
+ ""
+ ""
+ 579b6455f429d389;
+ b144d44b6d00f06dc1
+ ""
+ 88
+ ""
+ ""
+ c0feccc75a38a7ea;
+ d472a784e0c6f21195
+ ""
+ ""
+ a3
+ ba
+ d3e312ae74483320;
+ b9f4ae985511265feb
+ d11c164720eef9eb
+ 1c8dd0b00951f284649016ed00456331854bc78bf43966eb
+ 0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc
+ ececbe9f36ef004be708cf21bf97615f62e9ef58803fe723
+ 57ac52bfb40dd355;
+ 2810d858cbbc8424d1
+ 26b807e6
+ daa089c3f9099c5ffb8241
+ 73d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db
+ 7dff8ee32fab541aa59bdccc84961db26644f6bd50773640afd3a22cd438f54026
+ 916e18567fd17de8;
+ 8f48af65f7cc9e3fb9
+ 0e1721b730374f
+ fc9bc597f56ccbb2f294b38766fc69f6a9f2c0
+ 945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f09
+ 3c6ea417e98fd5ed2874ef3b1d8b512fbbe5449541a8912afce6b85441
+ 6c1dcdd2eef63a3e;
+}
+
+cast128-ocb1 {
+ 60d7bcda163547d348b7551195
+ e77022907dd1dff7
+ ""
+ ""
+ ""
+ 35fcd5e38e3b51ae;
+ dac5c9941d26d0c6eb14ad568f
+ 86edd1dc9268eeee
+ 53
+ ""
+ ""
+ 9750a7c045cb5fa6;
+ 3285a6ed810c9b689daaa9060d
+ 2d4b6003062365b0
+ ""
+ a5
+ 70
+ 2007ad9ceaa910e8;
+ 4364c76c160f11896c4794846e
+ cfa14a7130c9f137
+ ""
+ 120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d
+ 1d6fefbc39046f96c95a8e6a1b9dee24838ae0538c73cc2b
+ 367e4bd46fea6528;
+ 1f337f29549e6b0d27a4ba2340
+ 85406a6136512061
+ f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a
+ 21635c6d62c9269029df3e6057acc87638f508046733d9ff
+ 0754a41170bb62612e1224d955d5c65fb33c4331487b17fc
+ bf7b46ca9365175f;
+ 61cdbda3b3e9878731ebfedd47
+ 05e505da1435dcea
+ ""
+ a7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb6
+ 491c578a12863680495817bbb1be6bb5cd068da6c097a4d7454c4e8da0
+ d255ace5711af8ae;
+ 21b7f65b000961040ef2f9b2fc
+ 5fa450727a9b542c
+ de52ebfda19d0ccc520f215eb57bb3a4f3ebbb
+ b18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b9
+ 97a20b90075f6b8cd05b2c101043d92167fd921a71668f63a3c1115b0f
+ 202da1820f237005;
+ 3bf4f2aad2605f
+ aee2b03fb648e27f
+ ""
+ ""
+ ""
+ 31e566cec6e241d7;
+ ff63102758fe2b
+ 69ac26afa3349829
+ b9
+ ""
+ ""
+ ca2c2e57da61fa0b;
+ 4586306fed5415
+ 4f8f28523c03d4de
+ ""
+ 16
+ 5d
+ 85b6fa491dfc6955;
+ 00157846b710ee
+ 72807a2219bfb474
+ ""
+ fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d
+ 737de7976152fc336878cbbb9ede5469e5cc5d970933fd65
+ 8f8227129780dd53;
+ 42f70800df9fcb
+ aca48b77dba18919
+ 6d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f76
+ 8281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22
+ f2320eca3b003b64b91066ab2de93cdd408517d8a9728db9
+ 538a1fa6a7597e50;
+ 260c571b4a42bb
+ 8fdb233bfa6a5cfb
+ ""
+ 0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc815178487
+ 20c12e9ba584a56f7768fe92d9111a7eae80e149386c93d17f7904a41a
+ 48e10cd0a8be13c9;
+ 3f0eb5b647da67
+ 94c18b5337685a96
+ ed65b9aca338527ef19b09c063c46f88de9fd4
+ 1e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012
+ 55e5fad364bb32f3fa056d496f84874281576e690d72fa33be655966e4
+ a0b5a442a7297a49;
+ e4713df46795630e7952
+ d22bb02d7100b8b6
+ ""
+ ""
+ ""
+ 940a9694d41abe63;
+ 49377d20a8f083455b66
+ 3e4ee1315f3c8f2a
+ eb
+ ""
+ ""
+ 7b6cad447bf0e593;
+ fa921451dcd1af5813b7
+ 0d30ce2f1fef6ef3
+ ""
+ 15
+ 30
+ 536c60f6f1d83c94;
+ d0798391805da08da3ae
+ fc5f8584b7c5e617
+ ""
+ 669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e8
+ 1c485850e9c9b37abb599a800973920b660fd62c31d374a4
+ 3b5a7524db68ca3d;
+ 15f422cdf0c8e30308be
+ 3c31e6bc58c0b7ca
+ dcb658b970e47479a684b5aefa69a4cd52147ed12ca98698
+ 1a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d4
+ 097c9f86dc5ed84b2c4302fa4b10719337a1ee8feed7d101
+ 8f642bc221b793b9;
+ 4b6d00f06dc188d472a7
+ 84e0c6f21195a3b9
+ ""
+ f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00
+ 98a5dafa75c301e74727ecbba6a5047ed29491a660cef05ba70e74eaf4
+ eb2ef400c45349a9;
+ 456331854bc78bf43966
+ eb0cfa9138ddc399
+ 08445608fe95e81c2533e31c9c1a9851bc2810
+ d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f
+ b43644eaaa9f3060a3a2d0eb7b10f8829f2769eb4ceaed6b712550e71c
+ fb0381cb9425f488;
+ 30cbb7f0e4a973a8cd
+ 190107314717a774
+ ""
+ ""
+ ""
+ a084a9815a7601a4;
+ 56f3ff669c732b58db
+ 8f48af65f7cc9e3f
+ b9
+ ""
+ ""
+ 2ee2f881784c0227;
+ 0e1721b730374ffc9b
+ c597f56ccbb2f294
+ ""
+ b3
+ 05
+ 683231980af7d491;
+ 8766fc69f6a9f2c094
+ 5ffd505003cc0cae
+ ""
+ 9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65
+ e4f05c8136721b99369335ba402941018889f1fe75f9cb76
+ 88de859ee4e6c912;
+ cc1770a18cbfe6effd
+ 1ff6778554acf127
+ 0485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b
+ 480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a
+ db871dcb9e6624a931cef6ffcbe61ebc77c8b60f19550476
+ a74df4d69c389e3e;
+ 3e8128f8743d16687b
+ 7bb8deb9bd205b70
+ ""
+ e04c091d205cdad9e9a79b1abf91b0851e5ca605ac8451399587011677
+ 922755c3a636a359fcf8fbeda42c8de7d32d109c3d1e2bc6b7f7094e9b
+ f18c36d8b0f0d64b;
+ 508a15dde524af3e2b
+ ee0646541a42c2ec
+ ccb44d65bad397abfaf529ee41cf9a05c7efed
+ ef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a
+ c06849ccf2b34ffd7b497fd8936add1cb570227aa304c345092739d18b
+ 326e341574bedb1f;
+}
+
+cast128-pmac1 {
+ 60d7bcda163547d348b7551195
+ ""
+ 9908603f8e4ed537;
+ e77022907dd1dff7dac5c9941d
+ 26
+ ab2e2df52a4ffd51;
+ d0c6eb14ad568f86edd1dc9268
+ eeee533285a6ed810c9b689daaa9060d2d4b6003062365b0
+ 3400ed5412e2c9f7;
+ a54364c76c160f11896c479484
+ 6ecfa14a7130c9f137120634c9519848a877ff
+ 0f106ec05825e141;
+ 77bf79192a5b50
+ ""
+ 536bca927005ffd1;
+ ade5d9cd739a3d
+ 1f
+ f69b33db8f802d6e;
+ 337f29549e6b0d
+ 27a4ba234085406a6136512061f7080cc07df0591d8fa21f
+ 0b99429b96428cb3;
+ 2dd88374d8cde8
+ e160ad10997a21635c6d62c9269029df3e6057
+ 0098d1d07d912367;
+ acc87638f508046733d9
+ ""
+ da9779d1609cb9e1;
+ ff61cdbda3b3e9878731
+ eb
+ 00096e5430e6e2bd;
+ fedd4705e505da1435dc
+ eaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533
+ a91e29d999936af2;
+ 966f27043eb621b7f65b
+ 000961040ef2f9b2fc5fa450727a9b542cde52
+ 1df06f8b2c0f4c39;
+ ebfda19d0ccc520f21
+ ""
+ 78b9f4bb116ef26b;
+ 5eb57bb3a4f3ebbbb1
+ 8a
+ 57afa587a9a123d5;
+ c6c95a97a48030370c
+ 33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad260
+ d32f3f141a62efe1;
+ 5faee2b03fb648e27f
+ ff63102758fe2b69ac26afa3349829b9458630
+ cab1db46326dab8b;
+}
+
+cast128-ocb3 {
+ 60d7bcda163547d348b7551195
+ e77022907dd1
+ ""
+ ""
+ ""
+ 80acf79035879e49;
+ dff7dac5c9941d26d0c6eb14ad
+ 568f86edd1dc
+ 92
+ ""
+ ""
+ c1c0b7cf9333abd0;
+ 68eeee533285a6ed810c9b689d
+ aaa9060d2d4b
+ ""
+ 60
+ b7
+ 2ba34997b9b7c1e7;
+ 03062365b0a54364c76c160f11
+ 896c47
+ ""
+ 94846ecfa14a7130c9f137120634c9519848a877ff77bf79
+ a50349e70f84c21e91ac4dae8e84334c4eded066c4906f46
+ 044e9f72b51e120b;
+ 192a5b50ade5d9cd739a3d1f33
+ 7f29549e6b
+ 0d27a4ba234085406a6136512061f7080cc07df0591d8fa2
+ 1f2dd88374d8cde8e160ad10997a21635c6d62c9269029df
+ ff3c222bcd45bd08ed535a77e89023455b21fd6b198e5220
+ 6078eab50bffcabf;
+ 3e6057acc87638f508046733d9
+ ff61cdbda3b3
+ ""
+ e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a89447
+ c9cff5648431ab446232a4644f1c59af90abdc696868521a9632a765af
+ e993a7f8297d83bd;
+ 6b3f102b752eb9529533966f27
+ 043eb621b7f6
+ 5b000961040ef2f9b2fc5fa450727a9b542cde
+ 52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c
+ d94512471232da2099eee100523fb16bb45018f05f681f067aaf7af8d6
+ 87dca8c2d5779501;
+ 33d090c54215ab
+ d6b3ad54efc9
+ ""
+ ""
+ ""
+ da927642dafe6fd1;
+ a38378c5b93bf4
+ f2aad2605fae
+ e2
+ ""
+ ""
+ e890bed519c2bfc9;
+ b03fb648e27fff
+ 63102758fe2b
+ ""
+ 69
+ f6
+ a1e73f23ec2eddee;
+ ac26afa3349829
+ b94586
+ ""
+ 306fed54154f8f28523c03d4de1600157846b710ee72807a
+ 0cf707f93f9c389e7c78ef3e61d36d20604e1441b169fc9a
+ 6febc37ff410bc6f;
+ 2219bfb474fd71
+ d891f24bb6
+ 5d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcb
+ aca48b77dba189196d1ebba10b0467cb9fc2712a199e533f
+ 06e300b114e2b4bebe212cf694364bc44989b8cfe139b08a
+ b496b69d5f5f2406;
+ a9156308cdec3f
+ 768281e040a9
+ ""
+ b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb23
+ 0af7dab55d9223c86960d4b03e62b32f96a5c1ee581be399c93b15e789
+ 97f72d7c401cf252;
+ 3bfa6a5cfb0bad
+ 7d95214ade49
+ cb3b6f5fe8368131115c037ba323fe1dc81517
+ 84873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c0
+ a0f7f9f1e1934502280dfa21be7bd3eadab7541c17cccc03102dcb3454
+ 22cc4588498bc2a5;
+ 63c46f88de9fd41e72d7
+ b97e23e6eabd
+ ""
+ ""
+ ""
+ 869d689f3cb451ab;
+ ff3bcd211499268878db
+ f30f1dad89d4
+ b9
+ ""
+ ""
+ 10c4ca311ab0d4ea;
+ b12012e4713df4679563
+ 0e7952d22bb0
+ ""
+ 2d
+ ae
+ d91ecbfa408ed62c;
+ 7100b8b649377d20a8f0
+ 83455b
+ ""
+ 663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f
+ 447474323cef334fa9a0733f9dcca98a6f5f79b395392cea
+ 9b75ce84a39e878e;
+ 1fef6ef315d079839180
+ 5da08da3ae
+ fc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d
+ 264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0
+ 4e006eb2b0cb5e16f592ac6c5601c80e7a97fb0725c1ca4f
+ adcac831efd97e58;
+ b7cadcb658b970e47479
+ a684b5aefa69
+ ""
+ a4cd52147ed12ca986981a874498ad0abef8bc4fcb70e27e98ef1f0446
+ 9f8a879d391e2c63103be599717c39608d4f0d42ab0b17bb3515e1e210
+ d2579224689f1c51;
+ b42fb144d44b6d00f06d
+ c188d472a784
+ e0c6f21195a3b9f4ae985511265febd11c1647
+ 20eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0c
+ 87e39284c048d9c1660e5437f1cc86615724448c5c86d185b1a54bc05c
+ 52b0cf04002f103f;
+ fa9138ddc399084456
+ 08fe95e81c25
+ ""
+ ""
+ ""
+ 08923b4787ecca64;
+ 33e31c9c1a9851bc28
+ 10d858cbbc84
+ 24
+ ""
+ ""
+ 9c2d888635429e4f;
+ d126b807e6daa089c3
+ f9099c5ffb82
+ ""
+ 41
+ 76
+ 14aedb991bbdf5d5;
+ 73d7634c04226f30cb
+ b7f0e4
+ ""
+ a973a8cd190107314717a77456f3ff669c732b58db8f48af
+ ec093b797db58fa9c9b88e58ffbde6f4f4c38fb6db25b117
+ 3eeb6753ae39c984;
+ 65f7cc9e3fb90e1721
+ b730374ffc
+ 9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003
+ cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911
+ 3ffec2f705cc006637248de55ef480c9401790a303ccd564
+ 6d3b369a0699bf98;
+ e32d65cc1770a18cbf
+ e6effd1ff677
+ ""
+ 8554acf1270485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b
+ 91e2b0612406d31b88b044f838e29dc4bc08492a9d8b73b1751f6eb210
+ d684fc47c7b172f0;
+ 480aa3a4c84cef64f6
+ c9b53bf8f957
+ f4b03cf43e89957f9a3e8128f8743d16687b7b
+ b8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac84
+ f9bc629deb9e6dc3454415296389546e992975ef5c6dfba23357c06539
+ d4d1265b9cad7cee;
+}
+
+cast128-ocb3-mct {
+ 16 d2434caa22748e97;
+ 14 4dab36316a173b4c;
+ 12 25b37d39f09b8f7b;
+ 10 6ea2b818da01a012;
+ 8 e4e0aa59657d2246;
+ 6 29299e3845bdedad;
+ 4 99594416fa91c2f7;
+ 16 460ffc3b13c9;
+ 14 ff7bc7e6be51;
+ 12 e0a21b1ff4b7;
+ 10 5062cd9b7b51;
+ 8 5d40437352df;
+ 6 22a0f6279d79;
+ 4 429d09c799fc;
+ 16 a42ad529;
+ 14 9dec6cc9;
+ 12 15803553;
+ 10 5c50c831;
+ 8 4a2e5743;
+ 6 e10bbd1e;
+ 4 4a6bf7e7;
+}
--- /dev/null
+### Local tests for CAST256.
+
+cast256-cmac {
+ 60d7bcda163547d348b7551195
+ ""
+ 550f6aa2b500f5b19d32c63502e8448b;
+ e77022907dd1dff7dac5c9941d
+ 26
+ 198a435819e092069eaf3c5a455baf3c;
+ d0c6eb14ad568f86edd1dc9268
+ eeee533285a6ed810c9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f1371206
+ 2e7ac3fd9be8475d5b81a6f5fd3392e9;
+ 34c9519848a877ff77bf79192a
+ 5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd8
+ 7bcad81a16a4c1d1cf5fc4f107d9e50c;
+ 8374d8cde8e160ad10997a21
+ ""
+ 50fdac1d477bd12e61df27c230eb0858;
+ 635c6d62c9269029df3e6057
+ ac
+ 8ac07980a2538da61bf9fdb8f9791197;
+ c87638f508046733d9ff61cd
+ bda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb6
+ 4e9a7999789a6d1041fd26295aaa4942;
+ 21b7f65b000961040ef2f9b2
+ fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c5
+ ffbaaeeaf8f93c7c71c7708e21043c32;
+ 4215abd6b3ad54ef
+ ""
+ d3fc1c69dbbe8a358f5f968f8e60047e;
+ c9a38378c5b93bf4
+ f2
+ d37b1e960767df9d502e6c942e90f39d;
+ aad2605faee2b03f
+ b648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219
+ 55f8a2b6e7bd774ff32cac26cee4f1ef;
+ bfb474fd71d891f2
+ 4bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9f
+ d33ece086863448e6714580ec9f8d267;
+ c2712a199e533fa9156308cdec3f768281
+ ""
+ 9b818524f8ebef2f840938b85c30b9b8;
+ e040a9b9a222bd689aef66f5306ceb0c6b
+ 08
+ 44a2b05a0953086b802e5dfbccef8691;
+ ac8b0a22260c571b4a42bb8fdb233bfa6a
+ 5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65
+ ffa9d762bb11005e32a5747de41738c2;
+ b9aca338527ef19b09c063c46f88de9fd4
+ 1e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d
+ 4e21bb0835d28d84b50e6db35757d672;
+}
+
+cast256-ccm {
+ 60d7bcda163547d348b7551195
+ e77022907dd1dff7dac5c9
+ ""
+ ""
+ ""
+ aa9a4a79;
+ 941d26d0c6eb14ad568f86edd1
+ dc9268eeee533285a6ed81
+ 0c
+ ""
+ ""
+ c8a39dd0;
+ 9b689daaa9060d2d4b60030623
+ 65b0a54364c76c160f1189
+ ""
+ 6c
+ 2d
+ 73e78af5;
+ 4794846ecfa14a7130c9f13712
+ 0634c9519848a877ff
+ 77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd8
+ 8374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd47
+ af2bcbe02785e26888000200221db7ec8a96262bd4ac58f98de028ac5f0ab12ff4a6525254d7f78215727c2796d9de34
+ d83e04bccd4cc28ee89db0528d559b4c;
+ 05e505da1435dceaa7b1cc49ae
+ 1d50c38201a894476b
+ 3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0c
+ cc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb6
+ ae26d7c0fe93d7f36b4fe471099e64f0da7e0436df67adc9fbccbb9d12e26b9f086c3176ed28861c7d9afcfdb181dddb5b337c84b9
+ 4eb8907ccd4025021d7117364de8c4f9;
+ 48e27fff63102758fe2b69ac
+ 26afa3349829b94586306f
+ ""
+ ""
+ ""
+ dcee39b3;
+ ed54154f8f28523c03d4de16
+ 00157846b710ee72807a22
+ 19
+ ""
+ ""
+ d0f09e35;
+ bfb474fd71d891f24bb65d15
+ 63259f9eb53b571ea629c5
+ ""
+ 4d
+ b1
+ 20282dc8;
+ 57dd2d42f70800df9fcbaca4
+ 8b77dba189196d1ebb
+ a10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c57
+ 1b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da67
+ 9991d3ac6a6931127145d2ce4106eae3f0e588ed0e6a1c24d015d595640fe427ebb5753e1955ea8cfeca3dd0638b8e0b
+ a2dc9d2ee323e912007d462871314715;
+ 94c18b5337685a96ed65b9ac
+ a338527ef19b09c063
+ c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e
+ 7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d079839180
+ 1691f3064921baaa57137b92ce00739789fad53203a0c5c0683cad9da5e2a54c15b6ea69870a807b40fa2006fd631f790f43a88a86
+ d5f6f01586bd510672cd9f062d846013;
+ 5da08da3aefc5f85
+ 84b7c5e617669c0f16e398
+ ""
+ ""
+ ""
+ 7104d66a;
+ 15d4e9cfce3ed1ec
+ df3d264a7f16cb16c2e815
+ f4
+ ""
+ ""
+ d82c0d6e;
+ 22cdf0c8e30308be
+ 3c31e6bc58c0b7cadcb658
+ ""
+ b9
+ a6
+ cb4b7117;
+ 70e47479a684b5ae
+ fa69a4cd52147ed12c
+ a986981a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae98
+ 5511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608
+ 4763b77f7a624a9d1453034bea8d9c5061a93708adf6badc0e7372623212c427f6539c36f053398d051510adee65048f
+ 79884b4232ec8611c3e862865e3d60ec;
+ fe95e81c2533e31c
+ 9c1a9851bc2810d858
+ cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717a7
+ 7456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0c
+ fdfefeef8313360ebe5d7c5448129278ab19acbb0625d7e0675ce22a334269067523466c1cbad10c0a8630ae2d94d3b9a38dfe3db0
+ 2ba0749d5c88e7dde18a94a99bcc3b69;
+ ae9ce021a5f1fa4ffa91544485f1a1258b
+ 2b9b8f0911e32d65cc1770
+ ""
+ ""
+ ""
+ be73551e;
+ a18cbfe6effd1ff6778554acf1270485b2
+ 03a3c1c4c967c0a458cb94
+ 8b
+ ""
+ ""
+ 922ec10b;
+ dd409b687fa3a6827b480aa3a4c84cef64
+ f6c9b53bf8f957f4b03cf4
+ ""
+ 3e
+ 9e
+ ceadc769;
+ 89957f9a3e8128f8743d16687b7bb8deb9
+ bd205b70e04c091d20
+ 5cdad9e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397
+ abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a5718fd25014107
+ 882d1a8dcf897a5fd0b0a23aed8016eb4ba2290f47c51ffbb244fd10614dc98bdd072c8dd2607ccb0a8509c13141fc03
+ 541f7a6fcf2c319c9bdf291490aabd96;
+ c8e7d715a92add9589d1f5c054b2d98351
+ 4605ec590294a319b9
+ 802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe079753ee
+ 1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44
+ 87aacdd16e3d3bcd52d8bbbe6226bd5b405fd7ec9d93334a5ca599dfa600927a1270c54700d1d7ceb1fe25a033321359e98889bf74
+ 9c7c6db5629007318783e4fadc1f1d67;
+}
+
+cast256-eax {
+ 60d7bcda163547d348b7551195
+ ""
+ ""
+ ""
+ ""
+ 2b961641462baf0a23af6720a9197d0a;
+ e77022907dd1dff7dac5c9941d
+ 26
+ ""
+ ""
+ ""
+ c27ec7e5c6e5b2c0722a835e433f5708;
+ d0c6eb14ad568f86edd1dc9268
+ ""
+ ee
+ ""
+ ""
+ 91ee71af24a201bdc7dba1596261eced;
+ ee533285a6ed810c9b689daaa9
+ ""
+ ""
+ 06
+ 36
+ 21caca7994e9579e303e7c24be9fdb7f;
+ 0d2d4b6003062365b0a54364c7
+ 6c160f11896c4794846ecfa14a7130c9
+ f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7
+ 080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61
+ 242810649692db21e7595173fad46df3f55019d4e719ceb5bc09a733997fcacc846e6ec1e0589e4c9e5355dfaace122f
+ 4039884385c992be1a778520915dc0d6;
+ cdbda3b3e9878731ebfedd4705
+ e505da1435dceaa7b1cc49ae1d50c3
+ 8201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde
+ 52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad260
+ 6536f3d0bd3929eb609818c1cee5e2be47a1a02f0f883c34867f9966cfe97a31b2fd4c821c520e1be3d0a736dd1661b6190e24c1a6
+ 33856bece05f1ca8fe19b530e407b966;
+ 5faee2b03fb648e27fff6310
+ ""
+ ""
+ ""
+ ""
+ ee2162ee6e8410aa5200171d0c4024aa;
+ 2758fe2b69ac26afa3349829
+ b9
+ ""
+ ""
+ ""
+ 87a91471cda81dd33d9b42545c8b0b8c;
+ 4586306fed54154f8f28523c
+ ""
+ 03
+ ""
+ ""
+ 0e5e8f75620078311d835458946c93ff;
+ d4de1600157846b710ee7280
+ ""
+ ""
+ 7a
+ a6
+ 18d59976b1087c9b1790cc5e6b29d3ff;
+ 2219bfb474fd71d891f24bb6
+ 5d1563259f9eb53b571ea629c54d57dd
+ 2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222
+ bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe836813111
+ 303058fd583dbf8ab83aff89f31060650b03148c7330a6be6858eb1d384bac97798c4211f919b1170b2c1ce6d3d8b0da
+ 60ec12a7a132b714707aa1bfca3f3d67;
+ 5c037ba323fe1dc815178487
+ 3f0eb5b647da6794c18b5337685a96
+ ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89
+ d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d
+ efd6f1f344975f001595f2d1e3254791c4f1054f4e0932a85a28c1296308bad1c38aa7c2b2be16f2b14b94de98ce44d0255979ed5f
+ 335688afe647757a98f871ebf99933b7;
+ 30ce2f1fef6ef315
+ ""
+ ""
+ ""
+ ""
+ 57a1e64ab9765509b8abd4c36b616844;
+ d0798391805da08d
+ a3
+ ""
+ ""
+ ""
+ 9b3d0bae4a9f3fc0cc4135d73b6471e7;
+ aefc5f8584b7c5e6
+ ""
+ 17
+ ""
+ ""
+ 7a3a4fd12ec71c3058d3edc4416d6e56;
+ 669c0f16e39815d4
+ ""
+ ""
+ e9
+ 31
+ f15c15c0e14893b05d599ec77547c893;
+ cfce3ed1ecdf3d26
+ 4a7f16cb16c2e815f422cdf0c8e30308
+ be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a874498ad0abef8bc4fcb70e27e98
+ ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b009
+ dab10d1acc2f9596d131f83d22dfcb5f76e3133ae715429bb9ae30c6c41b4035ea2ba2e6d2b7afd41ffb821b88b0f11b
+ 2b770827aad8b1bfdf838506622ea7d6;
+ 51f284649016ed00
+ 456331854bc78bf43966eb0cfa9138
+ ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb82
+ 4173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc5
+ 180b3ae40e896c401aa0ec3a9323a97b3063486d3016f504ba931948fe5f48455bee3defdcec5d43d2e5b96f021f45027bf304c4a7
+ 36388109db5182725e7dc0c9e8c18e18;
+ 97f56ccbb2f294b38766fc69f6a9f2c094
+ ""
+ ""
+ ""
+ ""
+ 65d71bd58e0cfc24609eb320f26c4144;
+ 5ffd505003cc0cae9ce021a5f1fa4ffa91
+ 54
+ ""
+ ""
+ ""
+ 5c3f108cadaeed7fdc40c74003074e4a;
+ 4485f1a1258b2b9b8f0911e32d65cc1770
+ ""
+ a1
+ ""
+ ""
+ deb0b205c88084de69e4dcd20f94372f;
+ 8cbfe6effd1ff6778554acf1270485b203
+ ""
+ ""
+ a3
+ 7d
+ e854cf62bc9c693207ab3c89432f5418;
+ c1c4c967c0a458cb948bdd409b687fa3a6
+ 827b480aa3a4c84cef64f6c9b53bf8f9
+ 57f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac
+ 8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397abfaf529ee41cf9a05c7efedef340153
+ c8b37bf62703385c9441e1cdf357875ee437a15798e10c0717aefa605227bfffe401cfc610ae0b51d9f63e8098cc45bd
+ 4e68c56bb64b3d6ac08e35248a671884;
+ 9c51d2a90bbf7f1bfc338ab0ef5746ea8f
+ dcccd213e33f7e8a5718fd25014107
+ c8e7d715a92add9589d1f5c054b2d983514605ec590294a319b9802068a9f891bc5ba5afabf8c3122d12d7
+ ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7ab
+ 3afadb7496af2b3d618391fb535d6c6b42cb20a259c0f2d359d83055062b3f3c8715fbe13fe3b001c254ded295b2225e461ce11d2c
+ 77dafdf4ffbffd0bafdc4b2a1c2a77f8;
+}
+
+cast256-gcm {
+ 60d7bcda163547d348b7551195
+ ""
+ ""
+ ""
+ ""
+ e40bb3203b443cbb894937a4f69e6b67;
+ e77022907dd1dff7dac5c9941d
+ 26
+ ""
+ ""
+ ""
+ e9c2fa823e33d9aac0cdff0f79008a96;
+ d0c6eb14ad568f86edd1dc9268
+ ""
+ ee
+ ""
+ ""
+ c458bc5a2b89690b93e7d4603d8dc6c5;
+ ee533285a6ed810c9b689daaa9
+ ""
+ ""
+ 06
+ f3
+ a32741ffd61b5bb53b79a7df1e2e849f;
+ 0d2d4b6003062365b0a54364c7
+ 6c160f11896c4794846ecfa14a7130c9
+ f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7
+ 080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61
+ e8b2a245b1b44140bfde7f135603a3f4c088770181f486cee855087f0468fba9e4af3194c57ae401fd5304b6aca87204
+ 7ba17b157ad26810dcc34b7a04b11a38;
+ cdbda3b3e9878731ebfedd4705
+ e505da1435dceaa7b1cc49ae1d50c3
+ 8201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde
+ 52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad260
+ e635fd965a15d413b93196514d7a577123025a4559f16734464afea880e538b0193db7477e52720ce3554332f406382cec81b57972
+ c6fcab0d8311749afdfc54ff38f4484d;
+ 5faee2b03fb648e27fff6310
+ ""
+ ""
+ ""
+ ""
+ 96bb8800b41ff193d4b4c65f59d19dde;
+ 2758fe2b69ac26afa3349829
+ b9
+ ""
+ ""
+ ""
+ 0318bc05a63c0e2dc859b0f13dad85ae;
+ 4586306fed54154f8f28523c
+ ""
+ 03
+ ""
+ ""
+ 920fc4cab40ad51c11726fcb45c817ce;
+ d4de1600157846b710ee7280
+ ""
+ ""
+ 7a
+ f6
+ 947c572753bab643d56dd4095074acb1;
+ 2219bfb474fd71d891f24bb6
+ 5d1563259f9eb53b571ea629c54d57dd
+ 2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222
+ bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe836813111
+ c663c80f1a24265a81261cf9ae9b38ea937ddc6a3662815341fb9677608d8a1ed64d70bea85fed028af8f56563d9a8c6
+ 989401a20cf7eafc84c597493b6ad0a2;
+ 5c037ba323fe1dc815178487
+ 3f0eb5b647da6794c18b5337685a96
+ ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89
+ d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d
+ fbc42f92cbccbe0dcc288a2781c8b0156a3ca42294cda5f5ba134558d63dfc445e57c58f5a262dba7c4fe923071a49006b0df6c76c
+ 27f0a0861ef2ce9d671123efa0f6bc26;
+ 30ce2f1fef6ef315
+ ""
+ ""
+ ""
+ ""
+ 50e8f074272cc9a5a63212e7902d5df5;
+ d0798391805da08d
+ a3
+ ""
+ ""
+ ""
+ 16203fda45ef8d1249caf3413f1718fc;
+ aefc5f8584b7c5e6
+ ""
+ 17
+ ""
+ ""
+ fe964dc3fd7220defc4b718b74e1bcfb;
+ 669c0f16e39815d4
+ ""
+ ""
+ e9
+ 8f
+ 07b2a554d209d7f24549dceb24015bf2;
+ cfce3ed1ecdf3d26
+ 4a7f16cb16c2e815f422cdf0c8e30308
+ be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a874498ad0abef8bc4fcb70e27e98
+ ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b009
+ 1f97c51ad029f02dbebe7fd0faa41da5d523bf06055b9c13188549427c2b41f689be95c2a53dcd73a5497fbcd32b664d
+ 88fffe54f9bedb25fb5cd22f4d78b442;
+ 51f284649016ed00
+ 456331854bc78bf43966eb0cfa9138
+ ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb82
+ 4173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc5
+ 45170813ffb0c86e1d49c82c83b82d72ea126dbc788c27ec00b79ed4b266cbc66f9ef2311fb2c2464d1b81372dd120656250c427d0
+ 736070378d728b22d9844d97bde5e22e;
+ 97f56ccbb2f294b38766fc69f6a9f2c094
+ ""
+ ""
+ ""
+ ""
+ 7323880f89fb54d552c1a23505f238fb;
+ 5ffd505003cc0cae9ce021a5f1fa4ffa91
+ 54
+ ""
+ ""
+ ""
+ bbd60af0b8d37b6a322ab217d1d9cdc9;
+ 4485f1a1258b2b9b8f0911e32d65cc1770
+ ""
+ a1
+ ""
+ ""
+ 829cc05afc938051344df29091d390d6;
+ 8cbfe6effd1ff6778554acf1270485b203
+ ""
+ ""
+ a3
+ 5d
+ e3c0d0132c0bb48fe0424f4c72b763e8;
+ c1c4c967c0a458cb948bdd409b687fa3a6
+ 827b480aa3a4c84cef64f6c9b53bf8f9
+ 57f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac
+ 8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397abfaf529ee41cf9a05c7efedef340153
+ 59516d118aa9a72775326beb658de1e0cfb0cda583731d1d69b0b47d0b0cd441844618383dca21b165b19a0c11dec493
+ ae577e6433b84bef607dc9e0fcb9403a;
+ 9c51d2a90bbf7f1bfc338ab0ef5746ea8f
+ dcccd213e33f7e8a5718fd25014107
+ c8e7d715a92add9589d1f5c054b2d983514605ec590294a319b9802068a9f891bc5ba5afabf8c3122d12d7
+ ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7ab
+ 992b8af618edee3cfc8554dff63c15cb2767f995be01271c2cfd8fd552ba9736e3b40674bd386359c6ad649bd6ec0259891bdfdfcd
+ b50c46ca1142d5d4c72930495fa48515;
+}
+
+cast256-ocb1 {
+ 60d7bcda163547d348b7551195
+ e77022907dd1dff7dac5c9941d26d0c6
+ ""
+ ""
+ ""
+ f4e4aa5505f37af61a5a972c9fddc162;
+ eb14ad568f86edd1dc9268eeee
+ 533285a6ed810c9b689daaa9060d2d4b
+ 60
+ ""
+ ""
+ 584463e75d3ac1157672be951d0055a0;
+ 03062365b0a54364c76c160f11
+ 896c4794846ecfa14a7130c9f1371206
+ ""
+ 34
+ 5c
+ b394bb4ab2b10e6e8cf2367e54a31532;
+ c9519848a877ff77bf79192a5b
+ 50ade5d9cd739a3d1f337f29549e6b0d
+ ""
+ 27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e
+ 5e5c6671bcd32b508fcdf1290a9270f30ac874189f9e647431527ad1e4ff12bd82060a376c2668bbaa4716e80bbc9884
+ baeb21b394d13ec32b91057c7bf09405;
+ 6057acc87638f508046733d9ff
+ 61cdbda3b3e9878731ebfedd4705e505
+ da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5f
+ a450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54
+ 04f1f1082ac15c13cce9ec3c1fcbe8691ac8c736973073538f54a2cbc387064256e8add5a710c2102f0230773d54e1a7
+ 6e9c01e8e1cb63e1e545a84f84280577;
+ efc9a38378c5b93bf4f2aad260
+ 5faee2b03fb648e27fff63102758fe2b
+ ""
+ 69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9e
+ ffd476af7d1a5f68a96ecdfb466048936ba4d8c91e81057b23305c0d3120a0f30bfa23abcb7d3497912ceb161471933582a715b3ab
+ 1d3aa8cb71b538852d3e674e5bf3615d;
+ b53b571ea629c54d57dd2d42f7
+ 0800df9fcbaca48b77dba189196d1ebb
+ a10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b
+ 0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da67
+ 4d82601ad1a7e07573bed65ed8da86942029c74dc50df0e0f80b00bf3745f4266652f1e017340a07e94f96333f3333d61d0d940e5a
+ 34184bf2c44520892ed7e493d2af584a;
+ 94c18b5337685a96ed65b9ac
+ a338527ef19b09c063c46f88de9fd41e
+ ""
+ ""
+ ""
+ 09b578e0b6e9577963d2995dcd8f0bd5;
+ 72d7b97e23e6eabdff3bcd21
+ 1499268878dbf30f1dad89d4b9b12012
+ e4
+ ""
+ ""
+ 80b1ce3d1a2d08a260dcffd4a9f16abf;
+ 713df46795630e7952d22bb0
+ 2d7100b8b649377d20a8f083455b663e
+ ""
+ 4e
+ ce
+ afd445d169a181a0d3ab494c21e853e0;
+ e1315f3c8f2aebfa921451dc
+ d1af5813b70d30ce2f1fef6ef315d079
+ ""
+ 8391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e303
+ 4e1f0bbef82b78b779df16313c391c02bd6f7345ce682a14b23b2abb89a2096e54a1de1109e918c370716ebdc875b2d4
+ dffb8a8a04a9255086211180d478d1b7;
+ 08be3c31e6bc58c0b7cadcb6
+ 58b970e47479a684b5aefa69a4cd5214
+ 7ed12ca986981a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9
+ f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908
+ 499f455e969ad8bc52698430481a1c43a6cb786edb33fcde2407be7a18c6477d35d59eee05c523f870918e68500b78cd
+ 0d448fdf7f32a1b4ea521a182677dd36;
+ 445608fe95e81c2533e31c9c
+ 1a9851bc2810d858cbbc8424d126b807
+ ""
+ e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3f
+ 5d96f90a43251e531c7932bb2bd9b281f8281589ba1c490ddf3c57a32516eba4bd0eb418af024566da98156a0f83def4b51b2bb90f
+ 43fecf4cb095b89844141707fd0d2643;
+ b90e1721b730374ffc9bc597
+ f56ccbb2f294b38766fc69f6a9f2c094
+ 5ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff6
+ 778554acf1270485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f
+ ca44fbee713e258d9aea6a41b419530669e861a4c0beadc5653841d50680ab7fed4ad201ed83833d26e8afa66b8a91173eae53bc59
+ 82a696e7b8a54d2cbdceedfae2d7182b;
+ 9a3e8128f8743d16
+ 687b7bb8deb9bd205b70e04c091d205c
+ ""
+ ""
+ ""
+ d92ad5b9acbcf8fb954dbb262344b172;
+ dad9e9a79b1abf91
+ b0851e5ca605ac845139958701167750
+ 8a
+ ""
+ ""
+ e5e0cdba48ea323b69c3fd7873c61ac8;
+ 15dde524af3e2bee
+ 0646541a42c2ecccb44d65bad397abfa
+ ""
+ f5
+ 29
+ 989ebeaeb57f545955d5c2b8a76a5457;
+ 29ee41cf9a05c7ef
+ edef3401539c51d2a90bbf7f1bfc338a
+ ""
+ b0ef5746ea8fdcccd213e33f7e8a5718fd25014107c8e7d715a92add9589d1f5c054b2d983514605ec590294a319b980
+ f5017b00265a7b059589fe8549cd0d622805099dcf5d466a35dff3c0acbf40c1116ca692ec2388ec1fdbffdbfcc727f1
+ e00724826deae7efecaff58c6ff8dc4f;
+ 2068a9f891bc5ba5
+ afabf8c3122d12d7ff3c41122d70d17d
+ 4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68
+ daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4563d405e51881e99027b8ab9
+ 38e8e939b456444e7a6dd8dd56c53376dfa8896e37a9cd10b16c5a5a2daa0ee885a2d3df7925fe71b8ad09d35e722a8c
+ 81f8c645830a84009214a06300fc2feb;
+ aea3ccf860b00097
+ 40763d96836c5f87b95460938de1288c
+ ""
+ 69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c36800d9645563a308b
+ a7e718049be63223f6fcf229b7f907650bf6e10e8f53425f395df8b8aedf0658b001e1b1e717e75ba1b3750c9fa03714dbc5efeffa
+ e9fb84545896f7a672652dab4176b86b;
+ a60076817523bd2a
+ bf1261b089d8f23a9c2835076a23faac
+ 2cdd67771cc667a8331f0a170b66283e4f834a06148f302c3973accd56f6f24e33958b8c2e2352fd61e4fa
+ 8fec816ac861a8b33779f09e7a10fc02a8f48afa3080ee119a52a9a817e4f2b94b0820cab383a8cffeea7c486315799dc875fba578
+ e8f501b22016ada9cbfef68407a289863b7d3880603c3da8ea796352253441971cdd0171e8b57dcb32c58a078d439d523f36e17889
+ 2b2a2e481234b511a0fee70c0924f67c;
+ c8ec4837898a92142b5b0677da1ac27311
+ 7b45bcfff5d5f8b6fde2893232a9f81d
+ ""
+ ""
+ ""
+ c1cab79fe94cbf28ab64b07b34396c84;
+ 14517ffae475f6b94a43a67b3d380d2f9a
+ aafe2dd721c0095c8808847689211450
+ ba
+ ""
+ ""
+ 743df0e8509186cfb6ce313315f591df;
+ 8095ffab1eaadf66fd22ac1976063e113a
+ b61f813e28a1397a7974a1d7f4220c78
+ ""
+ 5f
+ 26
+ 503f2efabf0d67ef1e3ad58f79d6f17d;
+ e426a5a0e80f678d404147842941feeffd
+ c2eb44dc8c0d5e8f444f7f4e0c893959
+ ""
+ b74dc23a7bb40e7e0013e5150686d2301b43a15a84e81d7f5cedaa49e2414ebf47970e560475cff206877de69146acc3
+ 1e06a0e13fc9f0db0a30711b19af2ec7eaa3927ec5338711ceb30b6610c76e473b7a3668ece81dc0f73253a516413982
+ 53954399118d5578d98e208d426b0366;
+ ab6cf8556b7aa776945948d1b8834df219
+ 6c92ec1718dcdeee0d52d9539726d281
+ 0391b3f9d10c39b07ae8f08ce7cee4758a386a9943e97dedfbe61e737882cd09c2b9a80f34c0fde11c2481b11fc76bfa
+ 4dbf710a9e544e0c536ca1e040f9ad5b04140d98edabe08485290a4d87d13b07398a1458c2c6b61dbdbc1cccada8c1a0
+ a4d6895902d47c9ef748ad8517e2d12561e2c068f16250af0fed5f2e2ae5afbd7f207ba0511039c9ae5562d230a2fac4
+ 1ead7569ca82cb5cfd6b06fe6956c91e;
+ a9aabb6c4e3c3554f8fb1ef61614c27029
+ 5dfc0ca6551ca4bdb75359f91cb9d921
+ ""
+ 056b7de74fc9a9b37154ce6c0b396179d31f06a1dd5982cbc0d7cb23841da1ae8f4ae480cda98ad6cf2bacf6f9fd3f821330c43f3d
+ 0a97b9588a0aff4d72af4e22c74f318a40355d94e0e0b200a0f8d06d5bd9d54728665f613e0bba43618f384303c3332e7bb746ec9c
+ 99bb95cd33b76350d1b7de4543001f0e;
+ f6c2b3fac7cbcf96523d4723f91801325e
+ b8553236651c96788d73d192ee53b3f3
+ ebd66ddd98cedbe88e245de25b1593b70f8601562d90a9b59ed034a867642d25d54756fa5c47f16f64b837
+ bb4926214211a1c696ba172010abb433922a22d9fd881519165eb9d85197a21cc34ac0d5ae7be8dbf98e4ffed2cf6b1372a5aa47b5
+ a3a36df6117ba70650188e6b240237f97b545f08ad010f9eff2cc0a7ced297c38c495ac0f293cd4a6d9f56d96e31b17f64c7bcf949
+ 6bab5e7330a0c1f6a651f0a33e17327f;
+}
+
+cast256-pmac1 {
+ 60d7bcda163547d348b7551195
+ ""
+ e8bbe6976040b637c5730cead91a9243;
+ e77022907dd1dff7dac5c9941d
+ 26
+ afcd96681e4a0ed5af47bb8b17d41497;
+ d0c6eb14ad568f86edd1dc9268
+ eeee533285a6ed810c9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f1371206
+ b584d84fe844382627cede2f7c6e5299;
+ 34c9519848a877ff77bf79192a
+ 5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd8
+ b232cc4c44afe1700f942c996e05e589;
+ 8374d8cde8e160ad10997a21
+ ""
+ f0389f03e4cfb0f88b4016b8a96703bb;
+ 635c6d62c9269029df3e6057
+ ac
+ 754f863997eb465cc5ada5e2febd22a7;
+ c87638f508046733d9ff61cd
+ bda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb6
+ 407841bdebb8eb02d282ef5890f76dbf;
+ 21b7f65b000961040ef2f9b2
+ fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c5
+ 0ee25678e76d4bfd0bd892417f3a4aeb;
+ 4215abd6b3ad54ef
+ ""
+ d31ba003e87b06c6f0eb3c9e93090855;
+ c9a38378c5b93bf4
+ f2
+ cd4ec1c2080823a36b6a223b15c6f9db;
+ aad2605faee2b03f
+ b648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219
+ 8c621081c3ad80573f0003d5ed7b7ca8;
+ bfb474fd71d891f2
+ 4bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9f
+ a61047ab500558a62e494702a55f0426;
+ c2712a199e533fa9156308cdec3f768281
+ ""
+ d7db14580abbffd94087bd893c44bb9c;
+ e040a9b9a222bd689aef66f5306ceb0c6b
+ 08
+ f30bab211ce253887d48d7788411a8fd;
+ ac8b0a22260c571b4a42bb8fdb233bfa6a
+ 5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65
+ e7cb4245e3ce926311a964eaff43f853;
+ b9aca338527ef19b09c063c46f88de9fd4
+ 1e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d
+ 37e48b490fc5476f6a317210987af58c;
+}
+
+cast256-ocb3 {
+ 60d7bcda163547d348b7551195
+ e77022907dd1dff7dac5c9941d26
+ ""
+ ""
+ ""
+ 5d4fdb3278da8699e7a297755690b588;
+ d0c6eb14ad568f86edd1dc9268
+ eeee533285a6ed810c9b689daaa9
+ 06
+ ""
+ ""
+ fd23cef36d5d13dfbbc3f91a2edcbed2;
+ 0d2d4b6003062365b0a54364c7
+ 6c160f11896c4794846ecfa14a71
+ ""
+ 30
+ c1
+ 5890dc2ce6ae75f9c7072f3c06cc6aac;
+ c9f137120634c9519848a877ff
+ 77bf79192a5b50ade5d9cd
+ ""
+ 739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a
+ ba75fc237e106f6352333d944d8a6a0f8bfe641cf9242e343a63b4d591c2cdc18a6c50c88580b23e045876e62431d6d1
+ e9af104923e66478d2bbac836c025af7;
+ 21635c6d62c9269029df3e6057
+ acc87638f508046733d9ff61cd
+ bda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb6
+ 21b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a480
+ 856379775dd26a3b347f1e25434238aabccfbd70ecabff489dafd8d2d25fe86ae4cf09bd85f2c739f0365c4e7afb4bee
+ a43529bee26dd2393a369de5d2e23a55;
+ 30370c33d090c54215abd6b3ad
+ 54efc9a38378c5b93bf4f2aad260
+ ""
+ 5faee2b03fb648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219
+ 60e28a1e146d789fa2b63320cfd0dbb8de71aad2d5f2df5200a8c179db39e2a64e8f7bc0926ac95fc11a65cbd36935bc03c8b13dca
+ 3666a5ec5c24466c0680e3d6062b30fd;
+ bfb474fd71d891f24bb65d1563
+ 259f9eb53b571ea629c54d57dd2d
+ 42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040
+ a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c
+ 513e8a344d74844ef67effb6805688174ea7685fd8ba3a2860cd98864c5bcc699b69fe97963dcfbcda987b28e4d649ca5d45378a13
+ 6259e08c9387922cf33a2e5b86c23e38;
+ 037ba323fe1dc8151784873f
+ 0eb5b647da6794c18b5337685a96
+ ""
+ ""
+ ""
+ cfafee3e2ee7315fefeac9f823d4ec1e;
+ ed65b9aca338527ef19b09c0
+ 63c46f88de9fd41e72d7b97e23e6
+ ea
+ ""
+ ""
+ 8fd186584d18210cb316f19fea0bd516;
+ bdff3bcd211499268878dbf3
+ 0f1dad89d4b9b12012e4713df467
+ ""
+ 95
+ 33
+ d846c750ec238730ef2611b41ef1d22f;
+ 630e7952d22bb02d7100b8b6
+ 49377d20a8f083455b663e
+ ""
+ 4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f
+ 66e0593cdc31156b9cca5bbce514957973bd0186966333560fbc521e413fb7b3ce7189751f51708bf4424cca548a00b0
+ e4f02aebcee994443b0f438fd0d5e917;
+ 16e39815d4e9cfce3ed1ecdf
+ 3d264a7f16cb16c2e815f422cd
+ f0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a874498ad0abef8bc4f
+ cb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb
+ d182ac26587fc4ea051ef5e86830194d4f6afe030b7a72355dfc307eefffb85fc972a9e0ec73e25db66d4e98d8d7eb9d
+ 3905dfc881ebf47d63219f7a3824c03c;
+ 1c8dd0b00951f284649016ed
+ 00456331854bc78bf43966eb0cfa
+ ""
+ 9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f
+ fac401c9710f7a1adf621eef0169fd85bb9efd3e5a2a59f2d985c72665c3fe1043563eee9bcfe24902ea2a20565ee073c556c0897d
+ ea51bd57dadb6f1b4aa5b85471a9b725;
+ 30cbb7f0e4a973a8cd190107
+ 314717a77456f3ff669c732b58db
+ 8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0c
+ ae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967c0a4
+ 7f34458b9f7bdb1075bd95a6577649bc50bbfedeedb3eaadad5610c87416621c2496fb61c94ad5ac6d1d157556260ed4ee9762c5df
+ 4e98bd96daadb7ba8885c55080fd944f;
+ 58cb948bdd409b68
+ 7fa3a6827b480aa3a4c84cef64f6
+ ""
+ ""
+ ""
+ 54a6dca9e4f6b456ca9a72d5430bf37f;
+ c9b53bf8f957f4b0
+ 3cf43e89957f9a3e8128f8743d16
+ 68
+ ""
+ ""
+ 680d5049038160aeee6c7a4a3030990d;
+ 7b7bb8deb9bd205b
+ 70e04c091d205cdad9e9a79b1abf
+ ""
+ 91
+ c0
+ 3cf99a9f061f858ef7e0fb11d7f16467;
+ b0851e5ca605ac84
+ 51399587011677508a15dd
+ ""
+ e524af3e2bee0646541a42c2ecccb44d65bad397abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf7f1bfc338ab0
+ f364b814e500ef9ab50b1f0c5cc2bddd2c00e7622f85716506453739fbb85ebd7c9c5d6bb06e1ac7974b640bab4fb2e2
+ 538fef69d96b24725f40d036b7b6664e;
+ ef5746ea8fdcccd2
+ 13e33f7e8a5718fd25014107c8
+ e7d715a92add9589d1f5c054b2d983514605ec590294a319b9802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70
+ d17d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8
+ 4f968a35e00430a894fa0af39d8e46cbf5f6df56646d148532800533bc976923e4d9228a11def3ff976c6be7ccead573
+ 9722d670c7a13c44d3fb8e0e97446166;
+ ad68daac90cfe22d
+ 2f1f2968cc42fa8b669ed3bb3542
+ ""
+ a9cf44bbc8c6254d980398bd94e66eb4563d405e51881e99027b8ab9aea3ccf860b0009740763d96836c5f87b95460938de1288c69
+ 237f19a52651cdcd603091b3ca1b5d7a3131761987c0f38664d0432917123bbee65ccaa962fdee1431aa26d2f247e05df2017a6f73
+ 002e125c7224c549106c0c0f82d731ed;
+ d80ea12ff4bb5f06
+ 9b8a2e86041c1b9fc214e9ca2186
+ ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c36800d9645563a308ba60076817523bd2abf1261b089
+ d8f23a9c2835076a23faac2cdd67771cc667a8331f0a170b66283e4f834a06148f302c3973accd56f6f24e33958b8c2e2352fd61e4
+ 2094d61a83dedbd274dee89488d255879775fff59a5dcd4c270e2adab6e0d4ed7b48e867cd45400d77a667104d6a35a0056b5b9abe
+ dce0b2e1f5ba9e73aaff6246e384cbfe;
+ fa8fec816ac861a8b33779f09e7a10fc02
+ a8f48afa3080ee119a52a9a817e4
+ ""
+ ""
+ ""
+ 6dea6ebbce273e40bf6b5ba1481560d5;
+ f2b94b0820cab383a8cffeea7c48631579
+ 9dc875fba578c8ec4837898a9214
+ 2b
+ ""
+ ""
+ ef480ec30616d41fb86f4f79858304ca;
+ 5b0677da1ac273117b45bcfff5d5f8b6fd
+ e2893232a9f81d14517ffae475f6
+ ""
+ b9
+ 77
+ 8af99e141e67210c5239e5d4f6016e59;
+ 4a43a67b3d380d2f9aaafe2dd721c0095c
+ 8808847689211450ba8095
+ ""
+ ffab1eaadf66fd22ac1976063e113ab61f813e28a1397a7974a1d7f4220c785fe426a5a0e80f678d404147842941feef
+ b0315e2ce88fdc82212d14ff369becee4cc30d1e591bc73e9cb807b5014e50d2a03b416ccf7e403d0c788000d752c544
+ 565bb827571e2d4746ea15001c3a511c;
+ fdc2eb44dc8c0d5e8f444f7f4e0c893959
+ b74dc23a7bb40e7e0013e51506
+ 86d2301b43a15a84e81d7f5cedaa49e2414ebf47970e560475cff206877de69146acc3ab6cf8556b7aa776945948d1b8
+ 834df2196c92ec1718dcdeee0d52d9539726d2810391b3f9d10c39b07ae8f08ce7cee4758a386a9943e97dedfbe61e73
+ 6882d9145b766d004aa23db26e6727b910a52b3524cf41e5b079063a5690876e00b8446bd49b8fe0f96c646a9de22fd0
+ e1478799571f8ad2f2376901b4d0f0ba;
+ 7882cd09c2b9a80f34c0fde11c2481b11f
+ c76bfa4dbf710a9e544e0c536ca1
+ ""
+ e040f9ad5b04140d98edabe08485290a4d87d13b07398a1458c2c6b61dbdbc1cccada8c1a0a9aabb6c4e3c3554f8fb1ef61614c270
+ 9bfd938b0ddf7d005d20bab1060d8fae70cf3b084df0d31b76aeb0356f191bd9dd16f2a0ac6a6b4c910a7bb5982dc5ff5b7e99bf3a
+ 3fbd1c0a5b88616249b56c90758cdb29;
+ 295dfc0ca6551ca4bdb75359f91cb9d921
+ 056b7de74fc9a9b37154ce6c0b39
+ 6179d31f06a1dd5982cbc0d7cb23841da1ae8f4ae480cda98ad6cf2bacf6f9fd3f821330c43f3df6c2b3fa
+ c7cbcf96523d4723f91801325eb8553236651c96788d73d192ee53b3f3ebd66ddd98cedbe88e245de25b1593b70f8601562d90a9b5
+ a58bb37e7d47cb624edd3d81393569f1b6dfe1cc7e50af93187a22abdef670f81e2ec2e0ddbc5a4fce6f61bfd15e642128305d6026
+ 95512397bf2fdd2cb6111fd1763fe66b;
+}
+
+cast256-ocb3-mct {
+ 32 620ecceaf099c7d1772580169dbe93a0;
+ 28 95fc3dcdf6e2582e821ad38cd6c26391;
+ 24 acef03ad345af5000cb5ef196bd366b7;
+ 20 0f1a6f49f6853abb75ce4e90c58599ea;
+ 16 4258d565f5ec42869802cd5cd5d21a96;
+ 12 f8fc10048890fb153d71d846be4ce8ed;
+ 10 aaab0bbcaa81d7b3b5b1269a3761335e;
+ 8 329c9f836301b423469a56ad770da468;
+ 4 68fc11ed2e38d35ba5bf89af2c9f856c;
+ 32 c0310249248a38ff9950a833;
+ 28 b97c775bf1d0c8ef8284fee6;
+ 24 67a579e69bf507321be80304;
+ 20 7077b0ec786e90698b31f028;
+ 16 f326d6be1d1c2758e6bc69b1;
+ 12 8f3110db5963f2e800f22f06;
+ 10 58a1c2500f16812836519b52;
+ 8 3d0e35b1e0cb21f08410d22f;
+ 4 6d9f16f675839f35d0a9bf7d;
+ 32 af8a0e5cd2075f9c;
+ 28 9610c921db423fd5;
+ 24 e228f80e94e1fe31;
+ 20 a7a0f74679eb7543;
+ 16 b64ea6aa7a4d2c86;
+ 12 695dda9261b41e4f;
+ 10 27064d4c545536b5;
+ 8 1868f259d6049ec2;
+ 4 fc3fd6f530c8c94e;
+}
xchacha20 {
## Unfortunately, XChaCha isn't actually defined anywhere, even though it's
- ## obvious how to do it. These test vectors are from
- ## https://github.com/DaGenix/rust-crypto/blob/master/src/chacha20.rs
+ ## obvious how to do it.
+ ## These test vectors are from
+ ## https://github.com/DaGenix/rust-crypto/blob/master/src/chacha20.rs
1b27556473e985d462cd51197a9a46c76009549eac6474f206c4ee0844f68389
69696ee955b62b73cd62bda875fc73d68219e0036b7a0b37 "" 0 ""
4febf2fe4b359c508dc5e8b5980c88e38946d8f18f313465c862a08782648248018dacdcb904178853a46dca3a0eaaee747cba97434eaffad58fea8222047e0de6c3a6775106e0331ad714d2f27a55641340a1f1dd9f94532e68cb241cbdd150970d14e05c5b173193fb14f51c41f393835bf7f416a7e0bba81ffb8b13af0e21691d7ecec93b75e6e4183a;
+
+ ## This one's from draft-irtf-cfrg-xchacha-03.
+ 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f
+ 404142434445464748494a4b4c4d4e4f5051525354555658 "" 64
+ 5468652064686f6c65202870726f6e6f756e6365642022646f6c65222920697320616c736f206b6e6f776e2061732074686520417369617469632077696c6420646f672c2072656420646f672c20616e642077686973746c696e6720646f672e2049742069732061626f7574207468652073697a65206f662061204765726d616e20736865706865726420627574206c6f6f6b73206d6f7265206c696b652061206c6f6e672d6c656767656420666f782e205468697320686967686c7920656c757369766520616e6420736b696c6c6564206a756d70657220697320636c6173736966696564207769746820776f6c7665732c20636f796f7465732c206a61636b616c732c20616e6420666f78657320696e20746865207461786f6e6f6d69632066616d696c792043616e696461652e
+ 7d0a2e6b7f7c65a236542630294e063b7ab9b555a5d5149aa21e4ae1e4fbce87ecc8e08a8b5e350abe622b2ffa617b202cfad72032a3037e76ffdcdc4376ee053a190d7e46ca1de04144850381b9cb29f051915386b8a710b8ac4d027b8b050f7cba5854e028d564e453b8a968824173fc16488b8970cac828f11ae53cabd20112f87107df24ee6183d2274fe4c8b1485534ef2c5fbc1ec24bfc3663efaa08bc047d29d25043532db8391a8a3d776bf4372a6955827ccb0cdd4af403a7ce4c63d595c75a43e045f0cce1f29c8b93bd65afc5974922f214a40b7c402cdb91ae73c0b63615cdad0480680f16515a7ace9d39236464328a37743ffc28f4ddb324f4d0f5bbdc270c65b1749a6efff1fbaa09536175ccd29fb9e6057b307320d316838a9c71f70b5b5907a66f7ea49aadc409;
}
chacha8 {
000000000000000000000002 "" 0 ""
965e3bc6f9ec7ed9560808f4d229f94b137ff275ca9b3fcbdd59deaad23310ae;
}
+
+chacha20-poly1305 {
+ ## Test from RFC7539.
+ 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f
+ 070000004041424344454647
+ 50515253c0c1c2c3c4c5c6c7
+ 4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e
+ d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116
+ 1ae10b594f09e26a7e902ecbd0600691;
+
+ ## Test from draft-irtf-cfrg-xchacha-03.
+ 808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f
+ 404142434445464748494a4b4c4d4e4f5051525354555657
+ 50515253c0c1c2c3c4c5c6c7
+ 4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e
+ bd6d179d3e83d43b9576579493c0e939572a1700252bfaccbed2902c21396cbb731c7f1b0b4aa6440bf3a82f4eda7e39ae64c6708c54c216cb96b72e1213b4522f8c9ba40db5d945b11b69b982c1bb9e3f3fac2bc369488f76b2383565d3fff921f9664c97637da9768812f615c68b13b52e
+ c0875924c1c7987947deafd8780acf49;
+}
0e329232ea6d0d73 8787878787878787 0000000000000000;
}
+
+des-cmac {
+ bef260d7bcda1635
+ ""
+ 38adff25bb9e255b;
+ 47d348b7551195e7
+ 70
+ a70403c9dc15813e;
+ 22907dd1dff7dac5
+ c9941d26d0c6eb14ad568f86edd1dc9268eeee533285a6ed
+ 5e05047524a92169;
+ 810c9b689daaa906
+ 0d2d4b6003062365b0a54364c76c160f11896c
+ d345f04671d2f856;
+ 4794846ecfa14a
+ ""
+ d1f159eb76e2dcb3;
+ 7130c9f1371206
+ 34
+ 1728ecf20653375b;
+ c9519848a877ff
+ 77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4
+ 6f19d2ec30d3057a;
+ ba234085406a61
+ 36512061f7080cc07df0591d8fa21f2dd88374
+ 2b5a2cec413de519;
+}
+
+des-ccm {
+ bef260d7bcda1635
+ 47d348
+ ""
+ ""
+ ""
+ 97684266;
+ b7551195e7702290
+ 7dd1df
+ f7
+ ""
+ ""
+ 46cb911b;
+ dac5c9941d26d0c6
+ eb14ad
+ ""
+ 56
+ da
+ 952bf9f2;
+ 8f86edd1dc9268ee
+ ee533285a6
+ ed810c9b689daaa9060d2d4b6003062365b0a54364c76c16
+ 0f11896c4794846ecfa14a7130c9f137120634c9519848a8
+ cfdc3c0afd5fdd440f0e1898cb7cc518539e54d77a406117
+ 2c49a88b22b8108b;
+ 77ff77bf79192a5b
+ 50ade5d9cd
+ 739a3d1f337f29549e6b0d27a4ba234085406a
+ 6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a
+ fcd66aee455ff8c114978554c7a9debc11b642cff67c13f54f43c84302
+ 7c38973da8da2aec;
+ 21635c6d62c926
+ 9029df
+ ""
+ ""
+ ""
+ ce0d4ebc;
+ 3e6057acc87638
+ f50804
+ 67
+ ""
+ ""
+ 3e4ba751;
+ 33d9ff61cdbda3
+ b3e987
+ ""
+ 87
+ 41
+ 2a565655;
+ 31ebfedd4705e5
+ 05da1435dc
+ eaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533
+ 966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a
+ e1eaaf9f5e53008063e0e21e064025aa423fb9a0a86996d0
+ e257ab7ac4bc8b67;
+ 9b542cde52ebfd
+ a19d0ccc52
+ 0f215eb57bb3a4f3ebbbb18ac6c95a97a48030
+ 370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2
+ 52f8b409665916709096ea1116886f51d56d6f48f3e0c298f8ded5d660
+ 5d9404a726617d55;
+}
+
+des-eax {
+ bef260d7bcda1635
+ ""
+ ""
+ ""
+ ""
+ 4fd7b7ceb605971d;
+ 47d348b7551195e7
+ 70
+ ""
+ ""
+ ""
+ 362aa5d62008f0b2;
+ 22907dd1dff7dac5
+ ""
+ c9
+ ""
+ ""
+ da21b21da7d57854;
+ 941d26d0c6eb14ad
+ ""
+ ""
+ 56
+ 01
+ 91d13047c75395e9;
+ 8f86edd1dc9268ee
+ ee533285a6ed810c
+ 9b689daaa9060d2d4b6003062365b0a54364c76c160f1189
+ 6c4794846ecfa14a7130c9f137120634c9519848a877ff77
+ ff6584338c84f608f20f9b45387b79f759e4bbffdb97a914
+ a58397ff608476d2;
+ bf79192a5b50ade5
+ d9cd739a3d1f33
+ 7f29549e6b0d27a4ba234085406a6136512061
+ f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62
+ af4d58477434a67a527bd0abfbed0edc0e1d65db63ce387eee315f026a
+ e566a58b1afd6dde;
+ c9269029df3e60
+ ""
+ ""
+ ""
+ ""
+ ce840f6919760b2f;
+ 57acc87638f508
+ 04
+ ""
+ ""
+ ""
+ d2004b1898772d24;
+ 6733d9ff61cdbd
+ ""
+ a3
+ ""
+ ""
+ 7280bac984631a8b;
+ b3e9878731ebfe
+ ""
+ ""
+ dd
+ e8
+ 75dd11b7cf5f0dae;
+ 4705e505da1435
+ dceaa7b1cc49ae1d
+ 50c38201a894476b3f102b752eb9529533966f27043eb621
+ b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfd
+ 5cdd7720adf593db701494fc78e1bbd48e8fb79727cf09ad
+ b5c7ced07cae4060;
+ a19d0ccc520f21
+ 5eb57bb3a4f3eb
+ bbb18ac6c95a97a48030370c33d090c54215ab
+ d6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff6310
+ df23153076ea552eabc472d40d9c4e859e707cb2acc2d8aa7e828b949b
+ 01fcd2f2e30d870c;
+}
+
+des-gcm {
+ bef260d7bcda1635
+ ""
+ ""
+ ""
+ ""
+ b95298cbf804f0df;
+ 47d348b7551195e7
+ 70
+ ""
+ ""
+ ""
+ 22c33c13d4284fda;
+ 22907dd1dff7dac5
+ ""
+ c9
+ ""
+ ""
+ 32e3e11e770712c8;
+ 941d26d0c6eb14ad
+ ""
+ ""
+ 56
+ fa
+ 366c7284d32c1c2b;
+ 8f86edd1dc9268ee
+ ee533285a6ed810c
+ 9b689daaa9060d2d4b6003062365b0a54364c76c160f1189
+ 6c4794846ecfa14a7130c9f137120634c9519848a877ff77
+ 44f226038a81c0bf29f563401555ce1f15c8d35934f4757e
+ 19590fc8720cd177;
+ bf79192a5b50ade5
+ d9cd739a
+ 3d1f337f29549e6b0d27a4
+ ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10
+ 4cf8117a588a98676db9fcbc8fd592fc8e065354683bdde62cbdaec0ba89ef9a7e
+ 0ddf3556750fe18e;
+ 997a21635c6d62c9
+ 269029df3e6057
+ acc87638f508046733d9ff61cdbda3b3e98787
+ 31ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f10
+ bd611ed6e68f3bb8ae3b8b3eccae4a26c64ee9febe4fd46797bf634545
+ 5233b3b52edfd9b3;
+ 2b752eb9529533
+ ""
+ ""
+ ""
+ ""
+ deb6bb8d0f98e479;
+ 966f27043eb621
+ b7
+ ""
+ ""
+ ""
+ f72d871e2f82a356;
+ f65b000961040e
+ ""
+ f2
+ ""
+ ""
+ 12e8da9a09fd309b;
+ f9b2fc5fa45072
+ ""
+ ""
+ 7a
+ 06
+ 51a7355bf0814b08;
+ 9b542cde52ebfd
+ a19d0ccc520f215e
+ b57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215
+ abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb6
+ 4826d7b427e8d7dbfd700e8ef337210c86c2d5994781ebb0
+ 19ab2b84d1b8165a;
+ 48e27fff631027
+ 58fe2b69
+ ac26afa3349829b9458630
+ 6fed54154f8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f2
+ 43672e659b8698b44928111f7554e23e567bec8fd062387337d29a6f8332f563e3
+ c3ef31f3b831d4e9;
+ 4bb65d1563259f
+ 9eb53b571ea629
+ c54d57dd2d42f70800df9fcbaca48b77dba189
+ 196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040
+ c34cf61443b0c83d4120ed5e4ffd2469382732dfb776bc2ce6771cfaf6
+ 346dc157ce8660d5;
+}
+
+des-ocb1 {
+ bef260d7bcda1635
+ 47d348b7551195e7
+ ""
+ ""
+ ""
+ 1e777d9a35a9e879;
+ 7022907dd1dff7da
+ c5c9941d26d0c6eb
+ 14
+ ""
+ ""
+ 90dff887c781b59b;
+ ad568f86edd1dc92
+ 68eeee533285a6ed
+ ""
+ 81
+ 55
+ 5c9be7f28d9f3021;
+ 0c9b689daaa9060d
+ 2d4b6003062365b0
+ ""
+ a54364c76c160f11896c4794846ecfa14a7130c9f1371206
+ 98fabe1568fd4a31b60b6b90cc58dee9852314abdf9f4d89
+ 32bf6f1f094d55d1;
+ 34c9519848a877ff
+ 77bf79192a5b50ad
+ e5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136
+ 512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad
+ ec6d227abc440c6ece3ba42013676031c0fb2960d0d65985
+ 485047e83b3b11af;
+ 10997a21635c6d62
+ c9269029df3e6057
+ ""
+ acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da14
+ 1b7100307ae4b3ca2e3f973e2ccd11be6245f9b081a36cc023801d9a8f
+ 5e2e02663e595bc7;
+ 35dceaa7b1cc49ae
+ 1d50c38201a89447
+ 6b3f102b752eb9529533966f27043eb621b7f6
+ 5b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f21
+ 23ba63682d64c1e2ed3c14de44c492cf82ac3c63b1e85ae1d5905c1577
+ a2786c37e5b03355;
+ 5eb57bb3a4f3eb
+ bbb18ac6c95a97a4
+ ""
+ ""
+ ""
+ 846708610518ffc4;
+ 8030370c33d090
+ c54215abd6b3ad54
+ ef
+ ""
+ ""
+ 152246d59c398d68;
+ c9a38378c5b93b
+ f4f2aad2605faee2
+ ""
+ b0
+ 79
+ d74b0529249254f2;
+ 3fb648e27fff63
+ 102758fe2b69ac26
+ ""
+ afa3349829b94586306fed54154f8f28523c03d4de160015
+ 90d6861b964eed693b629e01188d4e50fcd236e71ccdc734
+ 0611bd11e7649655;
+ 7846b710ee7280
+ 7a2219bfb474fd71
+ d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f7
+ 0800df9fcbaca48b77dba189196d1ebba10b0467cb9fc271
+ 9fb915d584569a6bc699706d225c9f131bed57d39b7bb4e3
+ fdc4da4d6d428967;
+ 2a199e533fa915
+ 6308cdec3f768281
+ ""
+ e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb
+ 78e88cc7c809ee0d77e4550e3ba943fa3390b0e035bb4569fff7bc58ce
+ 821ba4f7ffd7cc02;
+ 8fdb233bfa6a5c
+ fb0bad7d95214ade
+ 49cb3b6f5fe8368131115c037ba323fe1dc815
+ 1784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09
+ e6b1c822199a5821020dea58a059635e7ceaa997c3bf8338bade196e39
+ 417dceee9a662328;
+}
+
+des-pmac1 {
+ bef260d7bcda1635
+ ""
+ 87398f9b84eacbd3;
+ 47d348b7551195e7
+ 70
+ c4a6d220ebf7ce9e;
+ 22907dd1dff7dac5
+ c9941d26d0c6eb14ad568f86edd1dc9268eeee533285a6ed
+ 9847df50037cb1ba;
+ 810c9b689daaa906
+ 0d2d4b6003062365b0a54364c76c160f11896c
+ fe45499fb92b19ae;
+ 4794846ecfa14a
+ ""
+ c7fc008258249c34;
+ 7130c9f1371206
+ 34
+ 5d742a297938a8a1;
+ c9519848a877ff
+ 77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4
+ 7cfba1467a3d156a;
+ ba234085406a61
+ 36512061f7080cc07df0591d8fa21f2dd88374
+ 0b547da65d93cc08;
+}
+
+des-ocb3 {
+ bef260d7bcda1635
+ 47d348b75511
+ ""
+ ""
+ ""
+ 4b59c22684f05b82;
+ 95e77022907dd1df
+ f7dac5c9941d
+ 26
+ ""
+ ""
+ 4cd9eea7a5f450a6;
+ d0c6eb14ad568f86
+ edd1dc9268ee
+ ""
+ ee
+ d2
+ c2fd51cbecc7d7da;
+ 533285a6ed810c9b
+ 689daa
+ ""
+ a9060d2d4b6003062365b0a54364c76c160f11896c479484
+ 5618b880cf7e0455afe09f1aa07e38de2eee04ffbba014a5
+ a22ffdfcd123b06f;
+ 6ecfa14a7130c9f1
+ 37120634c9
+ 519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29
+ 549e6b0d27a4ba234085406a6136512061f7080cc07df059
+ 7198f4d67f9d7ccae66e114745dd13b874d837fde0b5260a
+ e35c2d0fc8291130;
+ 1d8fa21f2dd88374
+ d8cde8e160ad
+ ""
+ 10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cd
+ a71a247ba8ca953a41dabaabf6c2c6a88f5e83c466a18fd8fd7b7595b8
+ f00ab9e066d2b84b;
+ bda3b3e9878731eb
+ fedd4705e505
+ da1435dceaa7b1cc49ae1d50c38201a894476b
+ 3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5f
+ ac3adc8ac7c662d73901110404b26e56622c2b0208a34517256ca0876b
+ a5bd20d0748afcc7;
+ a450727a9b542c
+ de52ebfda19d
+ ""
+ ""
+ ""
+ 0fe8c6e02dfc921b;
+ 0ccc520f215eb5
+ 7bb3a4f3ebbb
+ b1
+ ""
+ ""
+ 70f6e10b0765c5e5;
+ 8ac6c95a97a480
+ 30370c33d090
+ ""
+ c5
+ fc
+ e4a4438e74e98df5;
+ 4215abd6b3ad54
+ efc9a3
+ ""
+ 8378c5b93bf4f2aad2605faee2b03fb648e27fff63102758
+ 659653c7ad91a79469d940fa2363013b939286f21cc49eee
+ f15e30c3bfe7697d;
+ fe2b69ac26afa3
+ 349829b945
+ 86306fed54154f8f28523c03d4de1600157846b710ee7280
+ 7a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea6
+ ce4e983f478dbf2b09b3bad8af3dd6341645b8d4b492ff68
+ d1179f9268c3b779;
+ 29c54d57dd2d42
+ f70800df9fcb
+ ""
+ aca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cd
+ d337d3fd33b17c42b364dc862e8b85f506e4f444ed7f63ed4440b65bf8
+ 898fa93ba1e83b92;
+ ec3f768281e040
+ a9b9a222bd68
+ 9aef66f5306ceb0c6b08ac8b0a22260c571b4a
+ 42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c03
+ 139b42f78a74486d2488d4de046e14b0b8d9c49efc78718b87d5f72697
+ 8e529f719d87d2ee;
+}
+
+des-ocb3-mct {
+ 8 d3d27b14989225a9;
+ 7 eb3be38e3517c6d1;
+ 8 70d5d3c75417;
+ 7 93e83240fae6;
+ 8 bdc8b8e1;
+ 7 4407c007;
+}
0123456789abcdeffedcba987654321089abcdef01234567
0123456789abcde7 de0b7c06ae5e0ed5;
}
+
+des3-cmac {
+ ## Examples from NIST.
+
+ 0123456789abcdef23456789abcdef01
+ ""
+ 79ce52a7f786a960;
+ 0123456789abcdef23456789abcdef01
+ 6bc1bee22e409f96e93d7e117393172a
+ cc18a0b79af2413b;
+ 0123456789abcdef23456789abcdef01
+ 6bc1bee22e409f96e93d7e117393172aae2d8a57
+ c06d377ecd101969;
+ 0123456789abcdef23456789abcdef01
+ 6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51
+ 9cd33580f9b64dfb;
+
+ 0123456789abcdef23456789abcdef01456789abcdef0123
+ ""
+ 7db0d37df936c550;
+ 0123456789abcdef23456789abcdef01456789abcdef0123
+ 6bc1bee22e409f96e93d7e117393172a
+ 30239cf1f52e6609;
+ 0123456789abcdef23456789abcdef01456789abcdef0123
+ 6bc1bee22e409f96e93d7e117393172aae2d8a57
+ 6c9f3ee4923f6be2;
+ 0123456789abcdef23456789abcdef01456789abcdef0123
+ 6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51
+ 99429bd0bf7904e5;
+
+ ## Locally generated tests.
+ 60d7bcda163547d348b7551195e7
+ ""
+ 97b9dfb874462432;
+ 7022907dd1dff7dac5c9941d26d0
+ c6
+ f403026117612b0e;
+ eb14ad568f86edd1dc9268eeee53
+ 3285a6ed810c9b689daaa9060d2d4b6003062365b0a54364
+ 4e0fbacfa297003b;
+ c76c160f11896c4794846ecfa14a
+ 7130c9f137120634c9519848a877ff77bf7919
+ 19d5f833e07e2015;
+ 2a5b50ade5d9cd73
+ ""
+ ed38c0855386e014;
+ 9a3d1f337f29549e
+ 6b
+ c86e5386ee0e7b04;
+ 0d27a4ba23408540
+ 6a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8
+ d5306ab188df59b5;
+ e160ad10997a2163
+ 5c6d62c9269029df3e6057acc87638f5080467
+ b6fc8dee2287152c;
+ 33d9ff61cdbda3b3e9878731ebfedd47
+ ""
+ 349cd58ebc44cb39;
+ 05e505da1435dceaa7b1cc49ae1d50c3
+ 82
+ a8322086e22dbed8;
+ 01a894476b3f102b752eb9529533966f
+ 27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b54
+ 35c70f6e2cbab396;
+ 2cde52ebfda19d0ccc520f215eb57bb3
+ a4f3ebbbb18ac6c95a97a48030370c33d090c5
+ 639e5e64b410da07;
+ 4215abd6b3ad54efc9a38378c5b93bf4f2aad2605f
+ ""
+ 41240c9c71435050;
+ aee2b03fb648e27fff63102758fe2b69ac26afa334
+ 98
+ ab4c2c83747e8c5b;
+ 29b94586306fed54154f8f28523c03d4de16001578
+ 46b710ee72807a2219bfb474fd71d891f24bb65d1563259f
+ eff715a559241957;
+ 9eb53b571ea629c54d57dd2d42f70800df9fcbaca4
+ 8b77dba189196d1ebba10b0467cb9fc2712a19
+ 2753a7135b48898f;
+}
+
+des3-ccm {
+ 60d7bcda163547d348b7551195e7
+ 702290
+ ""
+ ""
+ ""
+ aa48bfd6;
+ 7dd1dff7dac5c9941d26d0c6eb14
+ ad568f
+ 86
+ ""
+ ""
+ 06de8798;
+ edd1dc9268eeee533285a6ed810c
+ 9b689d
+ ""
+ aa
+ 67
+ 35d148d9;
+ a9060d2d4b6003062365b0a54364
+ c76c160f11
+ 896c4794846ecfa14a7130c9f137120634c9519848a877ff
+ 77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4
+ a0cbf7ade835afc80d0244a41b72699e7f135479dcbf06f7
+ 9d8fd60bbb5deed9;
+ ba234085406a6136512061f7080c
+ c07df0591d
+ 8fa21f2dd88374d8cde8e160ad10997a21635c
+ 6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e98787
+ 09be940770a72970058ad3f06c973a2b58a7cc912892bc397eff73662e
+ 9146a93e7398cddb;
+ 31ebfedd4705e505
+ da1435
+ ""
+ ""
+ ""
+ 92740192;
+ dceaa7b1cc49ae1d
+ 50c382
+ 01
+ ""
+ ""
+ d1803413;
+ a894476b3f102b75
+ 2eb952
+ ""
+ 95
+ 63
+ c416162e;
+ 33966f27043eb621
+ b7f65b0009
+ 61040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc52
+ 0f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090
+ b70fe9f3c530c75595207f22867614779980e9ada1c35be5
+ 236101f21d127547;
+ c54215abd6b3ad54
+ efc9a38378
+ c5b93bf4f2aad2605faee2b03fb648e27fff63
+ 102758fe2b69ac26afa3349829b94586306fed54154f8f28523c03d4de
+ ffc2c6c900f35a8d4c0bc244cf5ebff8f9999f4ce5759b39131585d376
+ 9661947e6ea6d306;
+ 1600157846b710ee72807a2219bfb474
+ fd71d8
+ ""
+ ""
+ ""
+ 1afd62e9;
+ 91f24bb65d1563259f9eb53b571ea629
+ c54d57
+ dd
+ ""
+ ""
+ 9be5f1b8;
+ 2d42f70800df9fcbaca48b77dba18919
+ 6d1ebb
+ ""
+ a1
+ 2f
+ 8ec7e387;
+ 0b0467cb9fc2712a199e533fa9156308
+ cdec3f7682
+ 81e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a2226
+ 0c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b
+ 479741dd816d10d912b027aa913872636fc029c5b3b5e786
+ b52afd4780869038;
+ 6f5fe8368131115c037ba323fe1dc815
+ 1784873f0e
+ b5b647da6794c18b5337685a96ed65b9aca338
+ 527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd21149926
+ 2659d885994c1c74498d5caa2a19430c3622f508c1754794f736759134
+ 1fd64bfce60b9b7c;
+ 8878dbf30f1dad89d4b9b12012e4713df46795630e
+ 7952d2
+ ""
+ ""
+ ""
+ cbf3fe95;
+ 2bb02d7100b8b649377d20a8f083455b663e4ee131
+ 5f3c8f
+ 2a
+ ""
+ ""
+ 622e5637;
+ ebfa921451dcd1af5813b70d30ce2f1fef6ef315d0
+ 798391
+ ""
+ 80
+ 71
+ 1a8cd2c7;
+ 5da08da3aefc5f8584b7c5e617669c0f16e39815d4
+ e9cfce3ed1
+ ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6
+ bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147e
+ 820f2b98a0887f75cabdd9085299ba9d20e0c02e0e997019
+ 4b2b92958f792723;
+ d12ca986981a874498ad0abef8bc4fcb70e27e98ef
+ 1f0446b42f
+ b144d44b6d00f06dc188d472a784e0c6f21195
+ a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016
+ 04baa89b0f016a9eb9f9f555b539e33fde914515ab13f2506927f4a0db
+ 266553d3216d3444;
+}
+
+des3-eax {
+ 60d7bcda163547d348b7551195e7
+ ""
+ ""
+ ""
+ ""
+ fb8989aca27d4e49;
+ 7022907dd1dff7dac5c9941d26d0
+ c6
+ ""
+ ""
+ ""
+ d6928baa49d00fad;
+ eb14ad568f86edd1dc9268eeee53
+ ""
+ 32
+ ""
+ ""
+ 33a565f808e5486a;
+ 85a6ed810c9b689daaa9060d2d4b
+ ""
+ ""
+ 60
+ 79
+ a70d6c7cd5e64642;
+ 03062365b0a54364c76c160f1189
+ 6c4794846ecfa14a
+ 7130c9f137120634c9519848a877ff77bf79192a5b50ade5
+ d9cd739a3d1f337f29549e6b0d27a4ba234085406a613651
+ 9df7de45b395c138ed3f1c47399d41e00bad9d29625f6cbb
+ ffe26f440f8c69d8;
+ 2061f7080cc07df0591d8fa21f2d
+ d88374d8cde8e1
+ 60ad10997a21635c6d62c9269029df3e6057ac
+ c87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435
+ 698d38628b4297877182f76af79b7a17fafba3580f403a1c0645416006
+ 056a29aa5eec7e3b;
+ dceaa7b1cc49ae1d
+ ""
+ ""
+ ""
+ ""
+ cca6200e06749307;
+ 50c38201a894476b
+ 3f
+ ""
+ ""
+ ""
+ 71f50318e1a16b5d;
+ 102b752eb9529533
+ ""
+ 96
+ ""
+ ""
+ b553cae3d6e4ccb5;
+ 6f27043eb621b7f6
+ ""
+ ""
+ 5b
+ eb
+ 6f6d185a5644e5dc;
+ 000961040ef2f9b2
+ fc5fa450727a9b54
+ 2cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c9
+ 5a97a48030370c33d090c54215abd6b3ad54efc9a38378c5
+ 02f9df6832af2567bb074a96ff52ff9ef27cb6df55ed6912
+ 6919ed7c6d0c9686;
+ b93bf4f2aad2605f
+ aee2b03fb648e2
+ 7fff63102758fe2b69ac26afa3349829b94586
+ 306fed54154f8f28523c03d4de1600157846b710ee72807a2219bfb474
+ 332681d1ab4ad4e8eee4f4b578efee58c917514f4d3c8ca33f50281a53
+ 863ec2f3f702fa3a;
+ fd71d891f24bb65d1563259f9eb53b57
+ ""
+ ""
+ ""
+ ""
+ 80199187ffd10cea;
+ 1ea629c54d57dd2d42f70800df9fcbac
+ a4
+ ""
+ ""
+ ""
+ 54afba7a1543f424;
+ 8b77dba189196d1ebba10b0467cb9fc2
+ ""
+ 71
+ ""
+ ""
+ 9cb93469265f4d14;
+ 2a199e533fa9156308cdec3f768281e0
+ ""
+ ""
+ 40
+ 80
+ e97aceb64f2af2bb;
+ a9b9a222bd689aef66f5306ceb0c6b08
+ ac8b0a22260c571b
+ 4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8
+ 368131115c037ba323fe1dc8151784873f0eb5b647da6794
+ e9d68e86a6b48c7d9c78122bda02edc1b1419cb3031c60e4
+ 57fcc7556b89f2a9;
+ c18b5337685a96ed65b9aca338527ef1
+ 9b09c063c46f88
+ de9fd41e72d7b97e23e6eabdff3bcd21149926
+ 8878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d7100
+ f89817786143348d71bd1ee8d1016e7256a94589b86a3ce582d7a9a374
+ 0add4b3bd1159ff5;
+ b8b649377d20a8f083455b663e4ee1315f3c8f2aeb
+ ""
+ ""
+ ""
+ ""
+ f7c8ae1e42180c1a;
+ fa921451dcd1af5813b70d30ce2f1fef6ef315d079
+ 83
+ ""
+ ""
+ ""
+ b1dce877e070e318;
+ 91805da08da3aefc5f8584b7c5e617669c0f16e398
+ ""
+ 15
+ ""
+ ""
+ e373707f027e7557;
+ d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cd
+ ""
+ ""
+ f0
+ ef
+ b49b83dc48872748;
+ c8e30308be3c31e6bc58c0b7cadcb658b970e47479
+ a684b5aefa69a4cd
+ 52147ed12ca986981a874498ad0abef8bc4fcb70e27e98ef
+ 1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195
+ 81e03369c6ecf1d8fb8c84a9817e0481b6de9ab9312737a4
+ f9ad8a3df2d97500;
+ a3b9f4ae985511265febd11c164720eef9eb1c8dd0
+ b00951f2846490
+ 16ed00456331854bc78bf43966eb0cfa9138dd
+ c39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126
+ d05f8c73aa124cdfe56cd74db66498169f829858ed7ad4366d6388f6ae
+ 1a54e1c0b2765dd8;
+}
+
+des3-gcm {
+ 60d7bcda163547d348b7551195e7
+ ""
+ ""
+ ""
+ ""
+ 132e46ca9dbab9db;
+ 7022907dd1dff7dac5c9941d26d0
+ c6
+ ""
+ ""
+ ""
+ bfd51a7057175d5e;
+ eb14ad568f86edd1dc9268eeee53
+ ""
+ 32
+ ""
+ ""
+ d86615981ba738da;
+ 85a6ed810c9b689daaa9060d2d4b
+ ""
+ ""
+ 60
+ 58
+ ed191f4620eaf05c;
+ 03062365b0a54364c76c160f1189
+ 6c4794846ecfa14a
+ 7130c9f137120634c9519848a877ff77bf79192a5b50ade5
+ d9cd739a3d1f337f29549e6b0d27a4ba234085406a613651
+ aa3017ec2824335d1d4ced7dfa26a12168b7f1666fc0c262
+ 5f991803dc1e6270;
+ 2061f7080cc07df0591d8fa21f2d
+ d88374d8
+ cde8e160ad10997a21635c
+ 6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd
+ 9c0ed71aaf781676ef39d8f8e1fc9688f0bb74b4b13346ef27c096114375191d99
+ 1af29d5d8d54dd86;
+ 4705e505da1435dceaa7b1cc49ae
+ 1d50c38201a894
+ 476b3f102b752eb9529533966f27043eb621b7
+ f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f
+ 70bd822a653d5d478b5b833cba2e8317b4bc5cc0f3b63481cad478b43c
+ db44ad57ba2d5450;
+ 215eb57bb3a4f3eb
+ ""
+ ""
+ ""
+ ""
+ 1e48437f8a8d8ed9;
+ bbb18ac6c95a97a4
+ 80
+ ""
+ ""
+ ""
+ a5cbaee18d95f020;
+ 30370c33d090c542
+ ""
+ 15
+ ""
+ ""
+ 2d353887e03a32a7;
+ abd6b3ad54efc9a3
+ ""
+ ""
+ 83
+ 95
+ 7e18fe4cf4d6debd;
+ 78c5b93bf4f2aad2
+ 605faee2b03fb648
+ e27fff63102758fe2b69ac26afa3349829b94586306fed54
+ 154f8f28523c03d4de1600157846b710ee72807a2219bfb4
+ 4db1999e265acd8766761cb5b48a3d7bf61e264daf209900
+ c498552a4665b7a1;
+ 74fd71d891f24bb6
+ 5d156325
+ 9f9eb53b571ea629c54d57
+ dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533f
+ edcab4a157a12abde9e4743bd4d9351b0b6fe8c3b304c6daf3455197471e1eabdf
+ baf50f2e628a8632;
+ a9156308cdec3f76
+ 8281e040a9b9a2
+ 22bd689aef66f5306ceb0c6b08ac8b0a22260c
+ 571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131
+ 31865bdd67531355562674e18401ba3e453fc36b8390c5ef81802616fb
+ a837fdccf1d1647e;
+ 115c037ba323fe1dc8151784873f0eb5
+ ""
+ ""
+ ""
+ ""
+ b81a0ef79153b70a;
+ b647da6794c18b5337685a96ed65b9ac
+ a3
+ ""
+ ""
+ ""
+ a519f2296fa3debe;
+ 38527ef19b09c063c46f88de9fd41e72
+ ""
+ d7
+ ""
+ ""
+ 5ec4b107491149c1;
+ b97e23e6eabdff3bcd211499268878db
+ ""
+ ""
+ f3
+ 30
+ 0824b10396c7f8ba;
+ 0f1dad89d4b9b12012e4713df4679563
+ 0e7952d22bb02d71
+ 00b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa92
+ 1451dcd1af5813b70d30ce2f1fef6ef315d0798391805da0
+ 0237988024ea8379f5a851a1a1df21241c0f794ef45c528b
+ 0bc36677cc8cad46;
+ 8da3aefc5f8584b7c5e617669c0f16e3
+ 9815d4e9
+ cfce3ed1ecdf3d264a7f16
+ cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5
+ 0a501f6458635eb8074e565be165b71b922c8907caaa5bc385bb62a4f2711a70a5
+ d51e68d40adb01c0;
+ aefa69a4cd52147ed12ca986981a8744
+ 98ad0abef8bc4f
+ cb70e27e98ef1f0446b42fb144d44b6d00f06d
+ c188d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb
+ 7af7a90baa5a4ec5904454bd0d62a3beafc988913073eb04f3748af96a
+ 20721ecf26d54b13;
+ 1c8dd0b00951f284649016ed00456331854bc78bf4
+ ""
+ ""
+ ""
+ ""
+ ac407ef838e78ff3;
+ 3966eb0cfa9138ddc39908445608fe95e81c2533e3
+ 1c
+ ""
+ ""
+ ""
+ de0e93debf2119fd;
+ 9c1a9851bc2810d858cbbc8424d126b807e6daa089
+ ""
+ c3
+ ""
+ ""
+ 292a3b10a3279110;
+ f9099c5ffb824173d7634c04226f30cbb7f0e4a973
+ ""
+ ""
+ a8
+ 68
+ a0021d91c51fbdb5;
+ cd190107314717a77456f3ff669c732b58db8f48af
+ 65f7cc9e3fb90e17
+ 21b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0
+ 945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a125
+ e47c416a265254284ec5ab752f010377d4ff57d4296ce09e
+ 5e479801a05652fb;
+ 8b2b9b8f0911e32d65cc1770a18cbfe6effd1ff677
+ 8554acf1
+ 270485b203a3c1c4c967c0
+ a458cb948bdd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957f4b03cf4
+ 2d0fcd3ec8e72558fb6cad34d3a93a7ad4b5b5940fdc77c1dfd733a1ddf5e093d5
+ 2e35100e8d1e24fb;
+ 3e89957f9a3e8128f8743d16687b7bb8deb9bd205b
+ 70e04c091d205c
+ dad9e9a79b1abf91b0851e5ca605ac84513995
+ 87011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397ab
+ fc2c1515c5fc3f727fb3e98ba249a076c3da8668f5e89db6e7956de064
+ a2411e499cacffef;
+}
+
+des3-ocb1 {
+ 60d7bcda163547d348b7551195e7
+ 7022907dd1dff7da
+ ""
+ ""
+ ""
+ cbd24ffb264f16ad;
+ c5c9941d26d0c6eb14ad568f86ed
+ d1dc9268eeee5332
+ 85
+ ""
+ ""
+ a6e1ad4b16d8d99b;
+ a6ed810c9b689daaa9060d2d4b60
+ 03062365b0a54364
+ ""
+ c7
+ a2
+ df1618790e682c74;
+ 6c160f11896c4794846ecfa14a71
+ 30c9f137120634c9
+ ""
+ 519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29
+ 51d9c953558e88ed892717edb5839471bab17ebda859fa2d
+ 673b34362686d614;
+ 549e6b0d27a4ba234085406a6136
+ 512061f7080cc07d
+ f0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62
+ c9269029df3e6057acc87638f508046733d9ff61cdbda3b3
+ 9e9db1333c288d89f1d852453679fd4a9df932ee424b56e6
+ 0e15cfad6c6299f4;
+ e9878731ebfedd4705e505da1435
+ dceaa7b1cc49ae1d
+ ""
+ 50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b0009
+ 79f213b6e9d3b4a233652364a0741f0a3905112cdcc65fc6a1f02b20e1
+ fb385d47f056ea7a;
+ 61040ef2f9b2fc5fa450727a9b54
+ 2cde52ebfda19d0c
+ cc520f215eb57bb3a4f3ebbbb18ac6c95a97a4
+ 8030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605f
+ 1b7e1e5164841c4478deb10a87cc07f70db15af1b12790fb9f8ea16d79
+ e0d1715f5e9373c7;
+ aee2b03fb648e27f
+ ff63102758fe2b69
+ ""
+ ""
+ ""
+ 4b884a39fbc7c745;
+ ac26afa3349829b9
+ 4586306fed54154f
+ 8f
+ ""
+ ""
+ d445ece0ef590e55;
+ 28523c03d4de1600
+ 157846b710ee7280
+ ""
+ 7a
+ 0e
+ 020e28ecb1a51fd3;
+ 2219bfb474fd71d8
+ 91f24bb65d156325
+ ""
+ 9f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77
+ a683ff420e8f9ea9467dd595afc344a0d25d20ea01c93b21
+ 2748703cfe3e8226;
+ dba189196d1ebba1
+ 0b0467cb9fc2712a
+ 199e533fa9156308cdec3f768281e040a9b9a222bd689aef
+ 66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa
+ aad5b6cbb6216005d17943984bb41bc4b6ba873ca43cb46b
+ d2c66cd04f05868e;
+ 6a5cfb0bad7d9521
+ 4ade49cb3b6f5fe8
+ ""
+ 368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b533768
+ db8d34944ff3c0cdda5436416fb627c58f9b02d925b59a9b68fbbeda2a
+ 06b84a7b2c9665a4;
+ 5a96ed65b9aca338
+ 527ef19b09c063c4
+ 6f88de9fd41e72d7b97e23e6eabdff3bcd2114
+ 99268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d
+ db5cd9c16b245b3b5078d900f5d270cb81567d73703c2c95925a7237d3
+ eef56cad5b7f2ed2;
+ 7100b8b649377d20a8f083455b663e4e
+ e1315f3c8f2aebfa
+ ""
+ ""
+ ""
+ 56ad76ec7f013571;
+ 921451dcd1af5813b70d30ce2f1fef6e
+ f315d0798391805d
+ a0
+ ""
+ ""
+ 6542ea8693b8cd18;
+ 8da3aefc5f8584b7c5e617669c0f16e3
+ 9815d4e9cfce3ed1
+ ""
+ ec
+ 35
+ 90d173ba8349a22b;
+ df3d264a7f16cb16c2e815f422cdf0c8
+ e30308be3c31e6bc
+ ""
+ 58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed1
+ 64348fc5f46a28edab91b5d41e27ab352fa8ca90d322b603
+ b894f7a0cf918ae2;
+ 2ca986981a874498ad0abef8bc4fcb70
+ e27e98ef1f0446b4
+ 2fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae
+ 985511265febd11c164720eef9eb1c8dd0b00951f2846490
+ dc70ae429c73fd871a49ab5aea8ed37196a151ad8d09dc3c
+ f76847ab0c01c5bd;
+ 16ed00456331854bc78bf43966eb0cfa
+ 9138ddc399084456
+ ""
+ 08fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa0
+ 7fcb46d49d63ecf4d49c4578841b1cc435362eb989098c8729fa7c8b7c
+ 170621267d144a86;
+ 89c3f9099c5ffb824173d7634c04226f
+ 30cbb7f0e4a973a8
+ cd190107314717a77456f3ff669c732b58db8f
+ 48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc
+ b0ecb19f5804122fb10b38ce2354dd1b9001c8e4f96d9f3a8b054ef79b
+ e3cfbcf2b101c897;
+ 69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4f
+ fa91544485f1a125
+ ""
+ ""
+ ""
+ efc673f15d727525;
+ 8b2b9b8f0911e32d65cc1770a18cbfe6effd1ff677
+ 8554acf1270485b2
+ 03
+ ""
+ ""
+ 4be4ef9aa08e493e;
+ a3c1c4c967c0a458cb948bdd409b687fa3a6827b48
+ 0aa3a4c84cef64f6
+ ""
+ c9
+ 60
+ 3c76403cf147a5a0;
+ b53bf8f957f4b03cf43e89957f9a3e8128f8743d16
+ 687b7bb8deb9bd20
+ ""
+ 5b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac84
+ 6a5f5444d206a359b01efa29f51c6d3f13c050b663f1ea32
+ 4ed8de43ccd151ef;
+ 51399587011677508a15dde524af3e2bee0646541a
+ 42c2ecccb44d65ba
+ d397abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf
+ 7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a5718fd2501
+ db5dbdd217bb8761aea78de2a51b9ab2bcb9559bfae22dfa
+ 002834c8f3b3d2f1;
+ 4107c8e7d715a92add9589d1f5c054b2d983514605
+ ec590294a319b980
+ ""
+ 2068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70d17d4569eaff59
+ 9a6b4f24093acdff2a03f9a40494e1e6dd2ed10be75cdf9fb4381f7a1e
+ c492487046c80434;
+ a332ba58d5d5589bfe079753ee1a957eb6d6699e6b
+ 7ea2725cb2dac07e
+ cde95759ac46fee6dda7abc8ad68daac90cfe2
+ 2d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e6
+ 14bc7ec21221fab0d0a55be9d505c315ef5ef5a01c9a5d8c71c6a8a569
+ 598c7a7659a4ece7;
+}
+
+des3-pmac1 {
+ 60d7bcda163547d348b7551195e7
+ ""
+ 4ee97adb08a4f1ca;
+ 7022907dd1dff7dac5c9941d26d0
+ c6
+ 9280792119f1c90a;
+ eb14ad568f86edd1dc9268eeee53
+ 3285a6ed810c9b689daaa9060d2d4b6003062365b0a54364
+ d3b9cda12ef855c9;
+ c76c160f11896c4794846ecfa14a
+ 7130c9f137120634c9519848a877ff77bf7919
+ ccb225988c72647f;
+ 2a5b50ade5d9cd73
+ ""
+ 29b6cbd6a39de3ea;
+ 9a3d1f337f29549e
+ 6b
+ a44255ba14c7c82e;
+ 0d27a4ba23408540
+ 6a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8
+ 4ae6eee38bf7dfc3;
+ e160ad10997a2163
+ 5c6d62c9269029df3e6057acc87638f5080467
+ de786269abfb7dce;
+ 33d9ff61cdbda3b3e9878731ebfedd47
+ ""
+ 8e4e4d58688d0661;
+ 05e505da1435dceaa7b1cc49ae1d50c3
+ 82
+ 1eb3af80bd877e09;
+ 01a894476b3f102b752eb9529533966f
+ 27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b54
+ ba1f17ab53c77f9c;
+ 2cde52ebfda19d0ccc520f215eb57bb3
+ a4f3ebbbb18ac6c95a97a48030370c33d090c5
+ 614b8997f580de04;
+ 4215abd6b3ad54efc9a38378c5b93bf4f2aad2605f
+ ""
+ 79469a20ba34f900;
+ aee2b03fb648e27fff63102758fe2b69ac26afa334
+ 98
+ 69f377b3ea8e925c;
+ 29b94586306fed54154f8f28523c03d4de16001578
+ 46b710ee72807a2219bfb474fd71d891f24bb65d1563259f
+ 6e0adaf190bd2ea1;
+ 9eb53b571ea629c54d57dd2d42f70800df9fcbaca4
+ 8b77dba189196d1ebba10b0467cb9fc2712a19
+ 129deaeec0e03d30;
+}
+
+des3-ocb3 {
+ 60d7bcda163547d348b7551195e7
+ 7022907dd1df
+ ""
+ ""
+ ""
+ 9bd7647cc6fc5088;
+ f7dac5c9941d26d0c6eb14ad568f
+ 86edd1dc9268
+ ee
+ ""
+ ""
+ 651a2beca10057bf;
+ ee533285a6ed810c9b689daaa906
+ 0d2d4b600306
+ ""
+ 23
+ 61
+ 55bdc89a749be10d;
+ 65b0a54364c76c160f11896c4794
+ 846ecf
+ ""
+ a14a7130c9f137120634c9519848a877ff77bf79192a5b50
+ 04994fd2405c66040b24f1e112d12a373a5ded3204e93dfc
+ 4d28060d06c1e6c9;
+ ade5d9cd739a3d1f337f29549e6b
+ 0d27a4ba23
+ 4085406a6136512061f7080cc07df0591d8fa21f2dd88374
+ d8cde8e160ad10997a21635c6d62c9269029df3e6057acc8
+ bd32ead43e0c7e3cdf30ec74e82e9db51a480c4bce6dfdfe
+ 2440122fa77e088a;
+ 7638f508046733d9ff61cdbda3b3
+ e9878731ebfe
+ ""
+ dd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752e
+ e7086ac5c54bba010b3597e95d8035ba213d20c55f50558f13f3725cb8
+ 5f2cd9483cb3a2ac;
+ b9529533966f27043eb621b7f65b
+ 000961040ef2
+ f9b2fc5fa450727a9b542cde52ebfda19d0ccc
+ 520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215ab
+ 960f222b5a4b66a7a416bf51be1cbfbaffd7626fd3449cfac5ec66cd94
+ 0cfa7a7a8b52f6d3;
+ d6b3ad54efc9a383
+ 78c5b93bf4f2
+ ""
+ ""
+ ""
+ f3be635a1f9bbcfa;
+ aad2605faee2b03f
+ b648e27fff63
+ 10
+ ""
+ ""
+ 27972bc75183a1f2;
+ 2758fe2b69ac26af
+ a3349829b945
+ ""
+ 86
+ 6d
+ 1449c4672751ce11;
+ 306fed54154f8f28
+ 523c03
+ ""
+ d4de1600157846b710ee72807a2219bfb474fd71d891f24b
+ 2f9edc04b832738964e4ef2c18a17b1eaf8ec0a325e08b9d
+ df25c2d0f9430d6f;
+ b65d1563259f9eb5
+ 3b571ea629
+ c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba1
+ 0b0467cb9fc2712a199e533fa9156308cdec3f768281e040
+ c6b34746675339e4f07cc680e5b8e3e5da5541a92c659459
+ a6d7adc34d54cb89;
+ a9b9a222bd689aef
+ 66f5306ceb0c
+ ""
+ 6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49
+ 79c706a66a8ebc8376e149588ab5584dcc7d59a37782abce2725bf2831
+ 9d6ffb6e4cb098a5;
+ cb3b6f5fe8368131
+ 115c037ba323
+ fe1dc8151784873f0eb5b647da6794c18b5337
+ 685a96ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6
+ da06bb4d2dc9612e2b9e1f38b4a9cf88c5f93c0ebbc12dc6894c42fb73
+ 86be658d949b0120;
+ eabdff3bcd211499268878dbf30f1dad
+ 89d4b9b12012
+ ""
+ ""
+ ""
+ a2599ce8b6a5832e;
+ e4713df46795630e7952d22bb02d7100
+ b8b649377d20
+ a8
+ ""
+ ""
+ 1b9d7c64f893467a;
+ f083455b663e4ee1315f3c8f2aebfa92
+ 1451dcd1af58
+ ""
+ 13
+ d4
+ 7702114c8465f527;
+ b70d30ce2f1fef6ef315d0798391805d
+ a08da3
+ ""
+ aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf
+ 23275152a0a4c447adf86084cad8e537778f46150a4430aa
+ a44aba0c5685823a;
+ 3d264a7f16cb16c2e815f422cdf0c8e3
+ 0308be3c31
+ e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd5214
+ 7ed12ca986981a874498ad0abef8bc4fcb70e27e98ef1f04
+ 55917e61b80378e828b2cb53911b751df969fb0aaf39a0a1
+ cc006e8fa8f47da1;
+ 46b42fb144d44b6d00f06dc188d472a7
+ 84e0c6f21195
+ ""
+ a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016
+ 67426920d7bb581d90c8c9b561d504d9729a024b2d26a34233f624bf35
+ 3e0e6eaf9b8d41c2;
+ ed00456331854bc78bf43966eb0cfa91
+ 38ddc3990844
+ 5608fe95e81c2533e31c9c1a9851bc2810d858
+ cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cb
+ 42eff82d31f0ca1cb79604219601c56c9d4e60ea08ab0e2be33b87fd70
+ 70e2f64112ef6d62;
+ b7f0e4a973a8cd190107314717a77456f3ff669c73
+ 2b58db8f48af
+ ""
+ ""
+ ""
+ f8608b8da49f9700;
+ 65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2
+ f294b38766fc
+ 69
+ ""
+ ""
+ df345d63832f4e3d;
+ f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4ffa
+ 91544485f1a1
+ ""
+ 25
+ eb
+ 17c6a45486274633;
+ 8b2b9b8f0911e32d65cc1770a18cbfe6effd1ff677
+ 8554ac
+ ""
+ f1270485b203a3c1c4c967c0a458cb948bdd409b687fa3a6
+ 359c9f7d642db7d7d35ed57a183a25212c054d25a4de09e3
+ 065d208592dbdc5c;
+ 827b480aa3a4c84cef64f6c9b53bf8f957f4b03cf4
+ 3e89957f9a
+ 3e8128f8743d16687b7bb8deb9bd205b70e04c091d205cda
+ d9e9a79b1abf91b0851e5ca605ac8451399587011677508a
+ 271c63ace6900ca3d2ea38737ff73f9298b4f6484ff4c916
+ 32315b959ad39d8f;
+ 15dde524af3e2bee0646541a42c2ecccb44d65bad3
+ 97abfaf529ee
+ ""
+ 41cf9a05c7efedef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdc
+ 0a1bc356fb7cbe2959c09e1c504326d0544a16fa91596ca1bfbf69cd9f
+ 0c1a33dffaebcbb8;
+ ccd213e33f7e8a5718fd25014107c8e7d715a92add
+ 9589d1f5c054
+ b2d983514605ec590294a319b9802068a9f891
+ bc5ba5afabf8c3122d12d7ff3c41122d70d17d4569eaff59a332ba58d5
+ 0e2f842eda3840dd0b22d2e5ec4e7280d96916ca08fa43b74ce34d1be9
+ 32dc28ff4706c6fb;
+}
+
+des3-ocb3-mct {
+ 24 d3d27b14989225a9;
+ 21 eb3be38e3517c6d1;
+ 16 07135a64481e5862;
+ 14 812edbcd44bd9e1a;
+ 8 d3d27b14989225a9;
+ 7 eb3be38e3517c6d1;
+ 24 70d5d3c75417;
+ 21 93e83240fae6;
+ 16 58382ba741ab;
+ 14 6c492c0d482a;
+ 8 70d5d3c75417;
+ 7 93e83240fae6;
+ 24 bdc8b8e1;
+ 21 4407c007;
+ 16 0654310f;
+ 14 e2591768;
+ 8 bdc8b8e1;
+ 7 4407c007;
+}
00451338957377 4e6f772069732074 3fa40e8a984d4815;
0123456789abcdef 4e6f772069732074 3fa40e8a984d4815;
}
+
+desx-cmac {
+ 60d7bcda163547d348b7551195e770
+ ""
+ a63cd9292fdf838b;
+ 22907dd1dff7dac5c9941d26d0c6eb
+ 14
+ a750bb7618266464;
+ ad568f86edd1dc9268eeee533285a6
+ ed810c9b689daaa9060d2d4b6003062365b0a54364c76c16
+ 46adc2fa0e79b3b1;
+ 0f11896c4794846ecfa14a7130c9f1
+ 37120634c9519848a877ff77bf79192a5b50ad
+ 68ba5dd6b52f40fb;
+ e5d9cd739a3d1f33
+ ""
+ 3480b2e14686a332;
+ 7f29549e6b0d27a4
+ ba
+ 9bbb98b5d49df72c;
+ 234085406a613651
+ 2061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10
+ f2c52f3919204c2b;
+ 997a21635c6d62c9
+ 269029df3e6057acc87638f508046733d9ff61
+ e5acddb871d45625;
+ cdbda3b3e9878731ebfedd4705e505da
+ ""
+ 08febcce60b0e724;
+ 1435dceaa7b1cc49ae1d50c38201a894
+ 47
+ 80bdb1521243c0b1;
+ 6b3f102b752eb9529533966f27043eb6
+ 21b7f65b000961040ef2f9b2fc5fa450727a9b542cde52eb
+ 86e00e79a5a63fc9;
+ fda19d0ccc520f215eb57bb3a4f3ebbb
+ b18ac6c95a97a48030370c33d090c54215abd6
+ 9b4ee9b29a9da89c;
+ b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648
+ ""
+ 00413cee3fc9338f;
+ e27fff63102758fe2b69ac26afa3349829b94586306fed
+ 54
+ f0bda4592cdc8ed1;
+ 154f8f28523c03d4de1600157846b710ee72807a2219bf
+ b474fd71d891f24bb65d1563259f9eb53b571ea629c54d57
+ 88158a6ce8f67fb2;
+ dd2d42f70800df9fcbaca48b77dba189196d1ebba10b04
+ 67cb9fc2712a199e533fa9156308cdec3f7682
+ ebda61b856727ef6;
+}
+
+desx-ccm {
+ 60d7bcda163547d348b7551195e770
+ 22907d
+ ""
+ ""
+ ""
+ 8ec46476;
+ d1dff7dac5c9941d26d0c6eb14ad56
+ 8f86ed
+ d1
+ ""
+ ""
+ 5f3af780;
+ dc9268eeee533285a6ed810c9b689d
+ aaa906
+ ""
+ 0d
+ 81
+ 6bf70ba0;
+ 2d4b6003062365b0a54364c76c160f
+ 11896c4794
+ 846ecfa14a7130c9f137120634c9519848a877ff77bf7919
+ 2a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085
+ 0d411f5b72112442088bee58587f1b0acc6cdc2609b38528
+ 263feadb0d5a70aa;
+ 406a6136512061f7080cc07df0591d
+ 8fa21f2dd8
+ 8374d8cde8e160ad10997a21635c6d62c92690
+ 29df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd47
+ 0b9ff20737a20741c3caa6bdad16930cce5fdbe1754d211e15701f547f
+ 97f1a547f1179100;
+ 05e505da1435dcea
+ a7b1cc
+ ""
+ ""
+ ""
+ 001cf051;
+ 49ae1d50c38201a8
+ 94476b
+ 3f
+ ""
+ ""
+ f4d9c98e;
+ 102b752eb9529533
+ 966f27
+ ""
+ 04
+ a0
+ a8ed8162;
+ 3eb621b7f65b0009
+ 61040ef2f9
+ b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57b
+ b3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6
+ ab9b7c746d2bc3d9987a625049e1e17f09268f61914db075
+ af163edd14717f26;
+ b3ad54efc9a38378
+ c5b93bf4f2
+ aad2605faee2b03fb648e27fff63102758fe2b
+ 69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846
+ 222e460a7c0c877a3c3043bf46cd87c4b76b2dd7491d3d4dd22c8ea42f
+ c0d94d90dade32cb;
+ b710ee72807a2219bfb474fd71d891f2
+ 4bb65d
+ ""
+ ""
+ ""
+ bd9bb6dc;
+ 1563259f9eb53b571ea629c54d57dd2d
+ 42f708
+ 00
+ ""
+ ""
+ f24fb66d;
+ df9fcbaca48b77dba189196d1ebba10b
+ 0467cb
+ ""
+ 9f
+ cc
+ 099a7f96;
+ c2712a199e533fa9156308cdec3f7682
+ 81e040a9b9
+ a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42
+ bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe83681
+ 15c1c73b28a6b905f4b301d941b961156ea6f145334295df
+ b81b11f44423b169;
+ 31115c037ba323fe1dc8151784873f0e
+ b5b647da67
+ 94c18b5337685a96ed65b9aca338527ef19b09
+ c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f
+ 3999f0ebfb02f3e9163b462d325a844ada24367ab139617a32a4ac7f69
+ d7d9bc4926dce5fe;
+ 1dad89d4b9b12012e4713df46795630e7952d22bb02d71
+ 00b8b6
+ ""
+ ""
+ ""
+ e2278b44;
+ 49377d20a8f083455b663e4ee1315f3c8f2aebfa921451
+ dcd1af
+ 58
+ ""
+ ""
+ eb62b54e;
+ 13b70d30ce2f1fef6ef315d0798391805da08da3aefc5f
+ 8584b7
+ ""
+ c5
+ d7
+ 72d0dd81;
+ e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb
+ 16c2e815f4
+ 22cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479
+ a684b5aefa69a4cd52147ed12ca986981a874498ad0abef8
+ e709032bd184e5104714acdbd444b4ba1242692f504e8bbd
+ 0e8982b121c86359;
+ bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc188
+ d472a784e0
+ c6f21195a3b9f4ae985511265febd11c164720
+ eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa
+ 157111d7f22ece6942850acb95f131f9749eb8625c0b6cef13fc859b62
+ 690bf035ddf2b2db;
+}
+
+desx-eax {
+ 60d7bcda163547d348b7551195e770
+ ""
+ ""
+ ""
+ ""
+ ee1840d22093ec87;
+ 22907dd1dff7dac5c9941d26d0c6eb
+ 14
+ ""
+ ""
+ ""
+ 46bb7bcd888d7699;
+ ad568f86edd1dc9268eeee533285a6
+ ""
+ ed
+ ""
+ ""
+ 64df2aefb68d65ae;
+ 810c9b689daaa9060d2d4b60030623
+ ""
+ ""
+ 65
+ bb
+ 575efecd423272be;
+ b0a54364c76c160f11896c4794846e
+ cfa14a7130c9f137
+ 120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d
+ 1f337f29549e6b0d27a4ba234085406a6136512061f7080c
+ 2972fa4117846aea7de02f73eb27981c4b72524b1d8bfb72
+ abd123bd49b7e2e9;
+ c07df0591d8fa21f2dd88374d8cde8
+ e160ad10997a21
+ 635c6d62c9269029df3e6057acc87638f50804
+ 6733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49
+ 35a431ef317b963514e1de6dfb568191eaa1bc89028e5868bcd25a8a3c
+ 2693b4f76100e1df;
+ ae1d50c38201a894
+ ""
+ ""
+ ""
+ ""
+ c9fb343d394b7356;
+ 476b3f102b752eb9
+ 52
+ ""
+ ""
+ ""
+ 47b15722772ba414;
+ 9533966f27043eb6
+ ""
+ 21
+ ""
+ ""
+ 0d4b68956fb6f426;
+ b7f65b000961040e
+ ""
+ ""
+ f2
+ dd
+ 8371e2b42301e2b0;
+ f9b2fc5fa450727a
+ 9b542cde52ebfda1
+ 9d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a4803037
+ 0c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2
+ c199728a8cd014558621fcda5a5ce7765ba3770b43832210
+ 84815299c2507a60;
+ 605faee2b03fb648
+ e27fff63102758
+ fe2b69ac26afa3349829b94586306fed54154f
+ 8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24b
+ bd352eea02065aa6352132121df385b3135e6598f1bbb589ed2c6044f1
+ 6993814a37fada84;
+ b65d1563259f9eb53b571ea629c54d57
+ ""
+ ""
+ ""
+ ""
+ 0a53de56ab1af32b;
+ dd2d42f70800df9fcbaca48b77dba189
+ 19
+ ""
+ ""
+ ""
+ 2539d47126f0cf9f;
+ 6d1ebba10b0467cb9fc2712a199e533f
+ ""
+ a9
+ ""
+ ""
+ 395bc02e7eefec9a;
+ 156308cdec3f768281e040a9b9a222bd
+ ""
+ ""
+ 68
+ ba
+ eb13f2c72c06d835;
+ 9aef66f5306ceb0c6b08ac8b0a22260c
+ 571b4a42bb8fdb23
+ 3bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c03
+ 7ba323fe1dc8151784873f0eb5b647da6794c18b5337685a
+ be11a99ec28d932e8064d57a7d3b6530cb137b8c05c397f2
+ 9e116a03c63831e0;
+ 96ed65b9aca338527ef19b09c063c46f
+ 88de9fd41e72d7
+ b97e23e6eabdff3bcd211499268878dbf30f1d
+ ad89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20
+ 87f8e65dcf6034314eba4a952e6a6d0fc7595318f0cde2ba027276421e
+ 0c029e501b79f342;
+ a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af58
+ ""
+ ""
+ ""
+ ""
+ f784fa0ed911d8ec;
+ 13b70d30ce2f1fef6ef315d0798391805da08da3aefc5f
+ 85
+ ""
+ ""
+ ""
+ 14998b9f57e85a91;
+ 84b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a
+ ""
+ 7f
+ ""
+ ""
+ eaad2aaf758ba8cb;
+ 16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7ca
+ ""
+ ""
+ dc
+ c6
+ 05378e1a70ab191a;
+ b658b970e47479a684b5aefa69a4cd52147ed12ca98698
+ 1a874498ad0abef8
+ bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc188d4
+ 72a784e0c6f21195a3b9f4ae985511265febd11c164720ee
+ c5f5009fdbade4e487e8440429fc86aa782937bcdec0ca08
+ 6feaef25c63b0802;
+ f9eb1c8dd0b00951f284649016ed00456331854bc78bf4
+ 3966eb0cfa9138
+ ddc39908445608fe95e81c2533e31c9c1a9851
+ bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c
+ bf860edf5f2e423766bd979b97a8b90082ad8f015e2c24997603fe75e7
+ 783c8dbade8c11f5;
+}
+
+desx-gcm {
+ 60d7bcda163547d348b7551195e770
+ ""
+ ""
+ ""
+ ""
+ 3cbc7b1df84dfef7;
+ 22907dd1dff7dac5c9941d26d0c6eb
+ 14
+ ""
+ ""
+ ""
+ 37276edd9916fab0;
+ ad568f86edd1dc9268eeee533285a6
+ ""
+ ed
+ ""
+ ""
+ 88e93bc3d86c7bf8;
+ 810c9b689daaa9060d2d4b60030623
+ ""
+ ""
+ 65
+ 4b
+ 742b8f2a4982002f;
+ b0a54364c76c160f11896c4794846e
+ cfa14a7130c9f137
+ 120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d
+ 1f337f29549e6b0d27a4ba234085406a6136512061f7080c
+ ae84aba1c0a431bfee3521370654d195518e43fbbcae082e
+ 8ae1456ca69792a7;
+ c07df0591d8fa21f2dd88374d8cde8
+ e160ad10
+ 997a21635c6d62c9269029
+ df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da14
+ 4f97aead4260eff9a4c1e39ef827ce568f08fcb95f2245503953f5c1e5b02036fb
+ b685fc67d7bac453;
+ 35dceaa7b1cc49ae1d50c38201a894
+ 476b3f102b752e
+ b9529533966f27043eb621b7f65b000961040e
+ f2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3
+ e8df8e4af153dbf70d1517d2f6d388f02705dd53c25b7f5c9d7c6c60f8
+ fa07533070e3b62b;
+ ebbbb18ac6c95a97
+ ""
+ ""
+ ""
+ ""
+ 52880f24cb1c97c4;
+ a48030370c33d090
+ c5
+ ""
+ ""
+ ""
+ ea8c5fd1be78bb6b;
+ 4215abd6b3ad54ef
+ ""
+ c9
+ ""
+ ""
+ 6130a7a2a73d2517;
+ a38378c5b93bf4f2
+ ""
+ ""
+ aa
+ bf
+ 6a2baada10b09a4f;
+ d2605faee2b03fb6
+ 48e27fff63102758
+ fe2b69ac26afa3349829b94586306fed54154f8f28523c03
+ d4de1600157846b710ee72807a2219bfb474fd71d891f24b
+ 353616debc97a081ea320a9a6379498465389fc12a30c97e
+ 29ae2d4f192ff073;
+ b65d1563259f9eb5
+ 3b571ea6
+ 29c54d57dd2d42f70800df
+ 9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f
+ e098b62b321e856c615d30d670b21afbbecc1c01d58184165b0d766819f149ff4d
+ afd78ddc422cde3b;
+ 768281e040a9b9a2
+ 22bd689aef66f5
+ 306ceb0c6b08ac8b0a22260c571b4a42bb8fdb
+ 233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe
+ 44c55447399ff836d71fa8adc5975f7fe504a62f8a031d118e9bdb8592
+ 3aec6e5c527595ee;
+ 1dc8151784873f0eb5b647da6794c18b
+ ""
+ ""
+ ""
+ ""
+ b649714dae520d42;
+ 5337685a96ed65b9aca338527ef19b09
+ c0
+ ""
+ ""
+ ""
+ 0f7b54a0f0e759de;
+ 63c46f88de9fd41e72d7b97e23e6eabd
+ ""
+ ff
+ ""
+ ""
+ b5332afef45bc1e2;
+ 3bcd211499268878dbf30f1dad89d4b9
+ ""
+ ""
+ b1
+ d9
+ 7d02b1fcfd1d0d3e;
+ 2012e4713df46795630e7952d22bb02d
+ 7100b8b649377d20
+ a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813
+ b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584
+ 902dda67a4bf1b44cc8f2b788541da0946d53815390326c4
+ b2a841f844b8b948;
+ b7c5e617669c0f16e39815d4e9cfce3e
+ d1ecdf3d
+ 264a7f16cb16c2e815f422
+ cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd5214
+ cfb2568095e376c9f50aed2f781748b98a68629a13f81842b6ed3315fe03633a37
+ 9188774ecda5437a;
+ 7ed12ca986981a874498ad0abef8bc4f
+ cb70e27e98ef1f
+ 0446b42fb144d44b6d00f06dc188d472a784e0
+ c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f2
+ be0fd7ae8afa1502f49e7616bd5a20956f3ce40c05b3ec395eefc2ee91
+ d16dddd5c97d9dad;
+ 84649016ed00456331854bc78bf43966eb0cfa9138ddc3
+ ""
+ ""
+ ""
+ ""
+ 35514c76e6059f2d;
+ 9908445608fe95e81c2533e31c9c1a9851bc2810d858cb
+ bc
+ ""
+ ""
+ ""
+ 88e733af8182afbd;
+ 8424d126b807e6daa089c3f9099c5ffb824173d7634c04
+ ""
+ 22
+ ""
+ ""
+ fa4d035dde2e7d7c;
+ 6f30cbb7f0e4a973a8cd190107314717a77456f3ff669c
+ ""
+ ""
+ 73
+ 45
+ 706978229672282f;
+ 2b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc597
+ f56ccbb2f294b387
+ 66fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4ffa
+ 91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6ef
+ 9b5a4d527d5bc4c52350bb496dcbda3b072b99173b55d90d
+ 9b96c04ec2f5504e;
+ fd1ff6778554acf1270485b203a3c1c4c967c0a458cb94
+ 8bdd409b
+ 687fa3a6827b480aa3a4c8
+ 4cef64f6c9b53bf8f957f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd
+ 63b58db88053af9da1f93879beea44bee6faa6a2c672aefc6ec5517b273cecda73
+ edbc4b6c82c99d4d;
+ 205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605
+ ac845139958701
+ 1677508a15dde524af3e2bee0646541a42c2ec
+ ccb44d65bad397abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf
+ e6bc35974509d938a953ad32ae829a5cced3f2846e756fbc99247ae1d5
+ 623e465c7913e6b2;
+}
+
+desx-ocb1 {
+ 60d7bcda163547d348b7551195e770
+ 22907dd1dff7dac5
+ ""
+ ""
+ ""
+ caa9db9c2fd96b20;
+ c9941d26d0c6eb14ad568f86edd1dc
+ 9268eeee533285a6
+ ed
+ ""
+ ""
+ e3f19e04d004771a;
+ 810c9b689daaa9060d2d4b60030623
+ 65b0a54364c76c16
+ ""
+ 0f
+ ce
+ 274fa8d10ec38416;
+ 11896c4794846ecfa14a7130c9f137
+ 120634c9519848a8
+ ""
+ 77ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d
+ 286bf711ca2f9d9e6e3ea11390d46225834d56c3cadef9f3
+ 8a3e9e27a8bd1267;
+ 27a4ba234085406a6136512061f708
+ 0cc07df0591d8fa2
+ 1f2dd88374d8cde8e160ad10997a21635c6d62c9269029df
+ 3e6057acc87638f508046733d9ff61cdbda3b3e9878731eb
+ e9a1c82381cb138e2b635f58ec9ad77e81eee97cb9b725cf
+ 2c08bbda5c67ae28;
+ fedd4705e505da1435dceaa7b1cc49
+ ae1d50c38201a894
+ ""
+ 476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2
+ 77c71af12f7e75599be17868608c1e66a767d5324a43d136777c8298f2
+ da3b49f25c22648f;
+ fc5fa450727a9b542cde52ebfda19d
+ 0ccc520f215eb57b
+ b3a4f3ebbbb18ac6c95a97a48030370c33d090
+ c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e2
+ e93425b446b6e0ee7622d56eb8781430e61c0b79fbf75b5129e66be0df
+ aaae9e5df22ffd66;
+ 7fff63102758fe2b
+ 69ac26afa3349829
+ ""
+ ""
+ ""
+ 2454c6d4af0543c6;
+ b94586306fed5415
+ 4f8f28523c03d4de
+ 16
+ ""
+ ""
+ 57f09f05b22aed2a;
+ 00157846b710ee72
+ 807a2219bfb474fd
+ ""
+ 71
+ 07
+ 98a03e06427d6c6e;
+ d891f24bb65d1563
+ 259f9eb53b571ea6
+ ""
+ 29c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebb
+ 79bc018164ccf90123ed426c5e261171c67c69512e8f41b1
+ d83eb8863b890872;
+ a10b0467cb9fc271
+ 2a199e533fa91563
+ 08cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b
+ 08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95
+ 2b050493ae97a338a539cf0a46f443a137a90bce681c3cf7
+ cca806fe40ecdf0d;
+ 214ade49cb3b6f5f
+ e8368131115c037b
+ ""
+ a323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca3
+ 49d25f8e34f3dfac53f8409552f42c89167889d2cbe2af5ba0ba4c2dfc
+ 7051575c9d170e37;
+ 38527ef19b09c063
+ c46f88de9fd41e72
+ d7b97e23e6eabdff3bcd211499268878dbf30f
+ 1dad89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d
+ bfe9acab806680bdc205fdaf72e274eeec6698801454fc94a8c0c16262
+ 4f53c9ecfbb5f758;
+ 20a8f083455b663e4ee1315f3c8f2aeb
+ fa921451dcd1af58
+ ""
+ ""
+ ""
+ 0230f537d84fad83;
+ 13b70d30ce2f1fef6ef315d079839180
+ 5da08da3aefc5f85
+ 84
+ ""
+ ""
+ 03faa4ac602dc7ed;
+ b7c5e617669c0f16e39815d4e9cfce3e
+ d1ecdf3d264a7f16
+ ""
+ cb
+ 18
+ a514a198a9c98049;
+ 16c2e815f422cdf0c8e30308be3c31e6
+ bc58c0b7cadcb658
+ ""
+ b970e47479a684b5aefa69a4cd52147ed12ca986981a8744
+ 7fb1ffb913b75f8d4c7ea6e84a9f2fc911380d1b8ee343f6
+ 2a496d014b16a40a;
+ 98ad0abef8bc4fcb70e27e98ef1f0446
+ b42fb144d44b6d00
+ f06dc188d472a784e0c6f21195a3b9f4ae985511265febd1
+ 1c164720eef9eb1c8dd0b00951f284649016ed0045633185
+ 722aa22fa02f13d32187730cb051fa3b49fcd9a308a9d453
+ c59459ba824bc1a5;
+ 4bc78bf43966eb0cfa9138ddc3990844
+ 5608fe95e81c2533
+ ""
+ e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb
+ 86c1f74d4db77a90398574f168f83e6de15e6a2b7b2afa621590dc0404
+ 4543ce1f721609f4;
+ 824173d7634c04226f30cbb7f0e4a973
+ a8cd190107314717
+ a77456f3ff669c732b58db8f48af65f7cc9e3f
+ b90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945f
+ cfa9cfeddbc593bd6812352a35fa31e2a53b1840ea430ee8e2085d60da
+ 90bfab3707b05a6a;
+ fd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b
+ 2b9b8f0911e32d65
+ ""
+ ""
+ ""
+ 7a861a7d3af428f9;
+ cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1
+ c4c967c0a458cb94
+ 8b
+ ""
+ ""
+ ff1c4c7bc330ef39;
+ dd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f9
+ 57f4b03cf43e8995
+ ""
+ 7f
+ d2
+ b1cb7d2102d5c32c;
+ 9a3e8128f8743d16687b7bb8deb9bd205b70e04c091d20
+ 5cdad9e9a79b1abf
+ ""
+ 91b0851e5ca605ac8451399587011677508a15dde524af3e
+ 9bdb27bbfc7389090471f3cb7051cb8d1fd530005e21a93f
+ 3bd9da825a402482;
+ 2bee0646541a42c2ecccb44d65bad397abfaf529ee41cf
+ 9a05c7efedef3401
+ 539c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f
+ 7e8a5718fd25014107c8e7d715a92add9589d1f5c054b2d9
+ b569d836ce07d26017bdecdc06938abe11f29988e2ee4eaa
+ 7c12ae284dab4140;
+ 83514605ec590294a319b9802068a9f891bc5ba5afabf8
+ c3122d12d7ff3c41
+ ""
+ 122d70d17d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d669
+ c893ff49cfec7dfa04b6c966ff8e2de2dbca702ed6cd0416b4d1e12b2a
+ 4f6e8bdaed610893;
+ 9e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad
+ 68daac90cfe22d2f
+ 1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6
+ 254d980398bd94e66eb4563d405e51881e99027b8ab9aea3ccf860b000
+ e5977138d0d737d7b616047aa523dc1b7d5b5fb6fd20e26831a2f34bb8
+ 6e42e08c54165845;
+}
+
+desx-pmac1 {
+ 60d7bcda163547d348b7551195e770
+ ""
+ 4af29214a7b8f451;
+ 22907dd1dff7dac5c9941d26d0c6eb
+ 14
+ 497e34853501b17c;
+ ad568f86edd1dc9268eeee533285a6
+ ed810c9b689daaa9060d2d4b6003062365b0a54364c76c16
+ be4cb7dd9428ff3f;
+ 0f11896c4794846ecfa14a7130c9f1
+ 37120634c9519848a877ff77bf79192a5b50ad
+ bd394b556e88691a;
+ e5d9cd739a3d1f33
+ ""
+ cf37166cf40c5a63;
+ 7f29549e6b0d27a4
+ ba
+ 36f50dc5278f6d48;
+ 234085406a613651
+ 2061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10
+ afa0c00f1d78a165;
+ 997a21635c6d62c9
+ 269029df3e6057acc87638f508046733d9ff61
+ 0cb5b03ffdf32b7e;
+ cdbda3b3e9878731ebfedd4705e505da
+ ""
+ 12307602abf4cd83;
+ 1435dceaa7b1cc49ae1d50c38201a894
+ 47
+ 7b6c2a63bc1599df;
+ 6b3f102b752eb9529533966f27043eb6
+ 21b7f65b000961040ef2f9b2fc5fa450727a9b542cde52eb
+ ec16536d65cbf867;
+ fda19d0ccc520f215eb57bb3a4f3ebbb
+ b18ac6c95a97a48030370c33d090c54215abd6
+ b0548570d2b43e37;
+ b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648
+ ""
+ 1e5b6857738e4db7;
+ e27fff63102758fe2b69ac26afa3349829b94586306fed
+ 54
+ 3739adab4d52a786;
+ 154f8f28523c03d4de1600157846b710ee72807a2219bf
+ b474fd71d891f24bb65d1563259f9eb53b571ea629c54d57
+ 54f3e5fc1458f0a3;
+ dd2d42f70800df9fcbaca48b77dba189196d1ebba10b04
+ 67cb9fc2712a199e533fa9156308cdec3f7682
+ 462473f2102f3c1d;
+}
+
+desx-ocb3 {
+ 60d7bcda163547d348b7551195e770
+ 22907dd1dff7
+ ""
+ ""
+ ""
+ 421aa0e31e3c1a41;
+ dac5c9941d26d0c6eb14ad568f86ed
+ d1dc9268eeee
+ 53
+ ""
+ ""
+ 7bb6a8ce983ccb5e;
+ 3285a6ed810c9b689daaa9060d2d4b
+ 6003062365b0
+ ""
+ a5
+ 0d
+ ca4e70eaefa59040;
+ 4364c76c160f11896c4794846ecfa1
+ 4a7130
+ ""
+ c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd
+ d0075d682bb032d318f435f35ed9e7e0dd2e759b18346051
+ 3c5c9c5dab448848;
+ 739a3d1f337f29549e6b0d27a4ba23
+ 4085406a61
+ 36512061f7080cc07df0591d8fa21f2dd88374d8cde8e160
+ ad10997a21635c6d62c9269029df3e6057acc87638f50804
+ 2b0daddf1c1562ed4ec92feba5fc19abb1a7d7fe85035cc3
+ b574000108612b30;
+ 6733d9ff61cdbda3b3e9878731ebfe
+ dd4705e505da
+ ""
+ 1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f
+ f9d6ea23faa8a36974e06d38d9061790875f1e4523e9f8eccb89dd8c13
+ 73bdbd55cfa011e8;
+ 27043eb621b7f65b000961040ef2f9
+ b2fc5fa45072
+ 7a9b542cde52ebfda19d0ccc520f215eb57bb3
+ a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a3
+ 21b80b17c3caf1e5b5fdabe9f9ce4fec36e20cae0a9c9b1e85167041be
+ 68f794a0eb64f247;
+ 8378c5b93bf4f2aa
+ d2605faee2b0
+ ""
+ ""
+ ""
+ fd8891d8d9802520;
+ 3fb648e27fff6310
+ 2758fe2b69ac
+ 26
+ ""
+ ""
+ ce479a676926cc17;
+ afa3349829b94586
+ 306fed54154f
+ ""
+ 8f
+ d7
+ d92beba1b5d650db;
+ 28523c03d4de1600
+ 157846
+ ""
+ b710ee72807a2219bfb474fd71d891f24bb65d1563259f9e
+ 6818636db15d3a46dc05078583752a6a774b1b514bdea903
+ c5958bbdef31bba2;
+ b53b571ea629c54d
+ 57dd2d42f7
+ 0800df9fcbaca48b77dba189196d1ebba10b0467cb9fc271
+ 2a199e533fa9156308cdec3f768281e040a9b9a222bd689a
+ 22dfcb714017ac0ad765d20593b65444a234a59dd3fc1abb
+ aa605331fbc55268;
+ ef66f5306ceb0c6b
+ 08ac8b0a2226
+ ""
+ 0c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe83681
+ 40a58a44dd58cd9e44d06391edc4ec2916d3b29628c61ad9084f56cc29
+ 436c5a2b1728295f;
+ 31115c037ba323fe
+ 1dc815178487
+ 3f0eb5b647da6794c18b5337685a96ed65b9ac
+ a338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd2114
+ 2b6d4c2462ad510a000d9df521066c02a81e31d5873c66343deb78fce2
+ 77a855f0a7d42e18;
+ 99268878dbf30f1dad89d4b9b12012e4
+ 713df4679563
+ ""
+ ""
+ ""
+ 2685c7810bf996c5;
+ 0e7952d22bb02d7100b8b649377d20a8
+ f083455b663e
+ 4e
+ ""
+ ""
+ a25ea075d7bc735a;
+ e1315f3c8f2aebfa921451dcd1af5813
+ b70d30ce2f1f
+ ""
+ ef
+ ef
+ e4ea88484e9e6b1e;
+ 6ef315d0798391805da08da3aefc5f85
+ 84b7c5
+ ""
+ e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16
+ fd6a65b03ae4567f3c6a94e573da790cb684b8d5bd32e3fd
+ 754c91fb0050e81e;
+ c2e815f422cdf0c8e30308be3c31e6bc
+ 58c0b7cadc
+ b658b970e47479a684b5aefa69a4cd52147ed12ca986981a
+ 874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b
+ 5c9347f1dc4853413edfe418d369932c21212122dac2955d
+ 92362b5fed50868c;
+ 6d00f06dc188d472a784e0c6f21195a3
+ b9f4ae985511
+ ""
+ 265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854b
+ 6f62164db8d9a857e36ca6eef9bbdcba9d01743165ee7acd87fe754d0d
+ a55e71bcc128168d;
+ c78bf43966eb0cfa9138ddc399084456
+ 08fe95e81c25
+ 33e31c9c1a9851bc2810d858cbbc8424d126b8
+ 07e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd
+ 1c394e0b510d366554dd0afcb0c6b0b4e9437fb1c83355753863e2eec9
+ 86560f52894b7d41;
+ 190107314717a77456f3ff669c732b58db8f48af65f7cc
+ 9e3fb90e1721
+ ""
+ ""
+ ""
+ a4205f9ab2399111;
+ b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0
+ 945ffd505003
+ cc
+ ""
+ ""
+ 5078f8d6fa0e866a;
+ 0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911
+ e32d65cc1770
+ ""
+ a1
+ 32
+ 87fddf9b28a92f55;
+ 8cbfe6effd1ff6778554acf1270485b203a3c1c4c967c0
+ a458cb
+ ""
+ 948bdd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8
+ b1af8fefb936518c083e54b9c67363455a1f642e253c0918
+ 159d0ce2b235b273;
+ f957f4b03cf43e89957f9a3e8128f8743d16687b7bb8de
+ b9bd205b70
+ e04c091d205cdad9e9a79b1abf91b0851e5ca605ac845139
+ 9587011677508a15dde524af3e2bee0646541a42c2ecccb4
+ ef425d80e98f3681592695628ed0a816418fa5899b1d1d42
+ f29bb2c9e21839c7;
+ 4d65bad397abfaf529ee41cf9a05c7efedef3401539c51
+ d2a90bbf7f1b
+ ""
+ fc338ab0ef5746ea8fdcccd213e33f7e8a5718fd25014107c8e7d715a9
+ 2c4a2be80fd7d3f7b3b5a4ef05a6540fb6798601ad3623aaab10d0ac60
+ a1ed9a02743fa18a;
+ 2add9589d1f5c054b2d983514605ec590294a319b98020
+ 68a9f891bc5b
+ a5afabf8c3122d12d7ff3c41122d70d17d4569
+ eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2
+ 81c230d8f7e0294cbbb8fe659f94a74332801000f5b5f49b74ce635cc0
+ 9d5ceb6d322cfa12;
+}
+
+desx-ocb3-mct {
+ 24 b8a0fa1c0e3e1201;
+ 23 b8a0fa1c0e3e1201;
+ 16 08afcdeda8acc974;
+ 15 0c967b6cca833a3c;
+ 8 d3d27b14989225a9;
+ 7 eb3be38e3517c6d1;
+ 24 0418ab9332b6;
+ 23 0418ab9332b6;
+ 16 aff581b9de59;
+ 15 2b546df8e00c;
+ 8 70d5d3c75417;
+ 7 93e83240fae6;
+ 24 802690b2;
+ 23 802690b2;
+ 16 cf467380;
+ 15 c874e69c;
+ 8 bdc8b8e1;
+ 7 4407c007;
+}
--- /dev/null
+### Low-level tests for GCM multiplication.
+
+gcm-mul64 {
+ cde4bef260d7bcda
+ 163547d348b75511
+ c9ee47ed2b156ee9;
+ 95e77022907dd1df
+ f7dac5c9941d26d0
+ 6dbd5c9c416492a6;
+ c6eb14ad568f86ed
+ d1dc9268eeee5332
+ 08bdf4e9bf8c1f93;
+ 85a6ed810c9b689d
+ aaa9060d2d4b6003
+ 0cf6ee6642648823;
+ 062365b0a54364c7
+ 6c160f11896c4794
+ 79f08ae100e469b0;
+ 846ecfa14a7130c9
+ f137120634c95198
+ 9f105828be4871c9;
+ 48a877ff77bf7919
+ 2a5b50ade5d9cd73
+ 474a0e6c8b786a42;
+ 9a3d1f337f29549e
+ 6b0d27a4ba234085
+ 44071433860810ec;
+ 406a6136512061f7
+ 080cc07df0591d8f
+ a09f47fee5c90487;
+ a21f2dd88374d8cd
+ e8e160ad10997a21
+ d1a3ae2849f6e1b3;
+ 635c6d62c9269029
+ df3e6057acc87638
+ 4d02197152061f71;
+ f508046733d9ff61
+ cdbda3b3e9878731
+ 3b567fc5b2fad254;
+ ebfedd4705e505da
+ 1435dceaa7b1cc49
+ dee51993e134cdcf;
+ ae1d50c38201a894
+ 476b3f102b752eb9
+ 8e3e6132a84c2062;
+ 529533966f27043e
+ b621b7f65b000961
+ 262098e88d669837;
+ 040ef2f9b2fc5fa4
+ 50727a9b542cde52
+ ad129933b7f306e5;
+ ebfda19d0ccc520f
+ 215eb57bb3a4f3eb
+ 95e06cd4d7f6453a;
+ bbb18ac6c95a97a4
+ 8030370c33d090c5
+ 0acd90305b863292;
+ 4215abd6b3ad54ef
+ c9a38378c5b93bf4
+ 9f21b3656650b80d;
+ f2aad2605faee2b0
+ 3fb648e27fff6310
+ 53448ad6016b5a88;
+ 2758fe2b69ac26af
+ a3349829b9458630
+ 7a114f9030a64751;
+ 6fed54154f8f2852
+ 3c03d4de16001578
+ 91532dc3dcd1b8fe;
+ 46b710ee72807a22
+ 19bfb474fd71d891
+ 877c3092f14be92e;
+ f24bb65d1563259f
+ 9eb53b571ea629c5
+ 26fa6c3a6205f520;
+ 4d57dd2d42f70800
+ df9fcbaca48b77db
+ baa61b8ee2efee4b;
+ a189196d1ebba10b
+ 0467cb9fc2712a19
+ a7b5b29b8359b2d3;
+ 9e533fa9156308cd
+ ec3f768281e040a9
+ 30ae2526b8601e66;
+ b9a222bd689aef66
+ f5306ceb0c6b08ac
+ 3656b2206364b85f;
+ 8b0a22260c571b4a
+ 42bb8fdb233bfa6a
+ 351d3f9025791fb4;
+ 5cfb0bad7d95214a
+ de49cb3b6f5fe836
+ 3c571fdf110d88d3;
+ 8131115c037ba323
+ fe1dc8151784873f
+ a5280a7d7bf3fbd5;
+ 0eb5b647da6794c1
+ 8b5337685a96ed65
+ 15a80ceb4c5612d9;
+ b9aca338527ef19b
+ 09c063c46f88de9f
+ 506d2129368b3535;
+ d41e72d7b97e23e6
+ eabdff3bcd211499
+ a9485bc115054e16;
+ 268878dbf30f1dad
+ 89d4b9b12012e471
+ d33c8040301aa9d6;
+ 3df46795630e7952
+ d22bb02d7100b8b6
+ c351d03535b15a43;
+ 49377d20a8f08345
+ 5b663e4ee1315f3c
+ 659490124597d0ac;
+ 8f2aebfa921451dc
+ d1af5813b70d30ce
+ a1265ff538452f9b;
+ 2f1fef6ef315d079
+ 8391805da08da3ae
+ 090119c5295ce005;
+ fc5f8584b7c5e617
+ 669c0f16e39815d4
+ fc0d6997230f9340;
+ e9cfce3ed1ecdf3d
+ 264a7f16cb16c2e8
+ 173b0d65b7f7defa;
+ 15f422cdf0c8e303
+ 08be3c31e6bc58c0
+ 95789ad1072e5991;
+ b7cadcb658b970e4
+ 7479a684b5aefa69
+ 5681dbf13399af21;
+ a4cd52147ed12ca9
+ 86981a874498ad0a
+ 69266124234d8824;
+ bef8bc4fcb70e27e
+ 98ef1f0446b42fb1
+ 9ce3c0c2bd679e5d;
+ 44d44b6d00f06dc1
+ 88d472a784e0c6f2
+ d4d0dde377de138c;
+ 1195a3b9f4ae9855
+ 11265febd11c1647
+ 324150243bf34600;
+ 20eef9eb1c8dd0b0
+ 0951f284649016ed
+ 15cb17aa733f44ba;
+ 00456331854bc78b
+ f43966eb0cfa9138
+ 4c8fd598a01bf479;
+ ddc39908445608fe
+ 95e81c2533e31c9c
+ 5341133994016920;
+ 1a9851bc2810d858
+ cbbc8424d126b807
+ 470ff40df79063ab;
+ e6daa089c3f9099c
+ 5ffb824173d7634c
+ 0a778cecd0cafb7a;
+ 04226f30cbb7f0e4
+ a973a8cd19010731
+ 85a0294ea292354a;
+ 4717a77456f3ff66
+ 9c732b58db8f48af
+ 636a37a3d5c97941;
+ 65f7cc9e3fb90e17
+ 21b730374ffc9bc5
+ 64dccdd7dfb08b84;
+ 97f56ccbb2f294b3
+ 8766fc69f6a9f2c0
+ bf6f50d14cf7e5b8;
+ 945ffd505003cc0c
+ ae9ce021a5f1fa4f
+ 37035c953d053e5f;
+ fa91544485f1a125
+ 8b2b9b8f0911e32d
+ 9c50f40823733f0b;
+ 65cc1770a18cbfe6
+ effd1ff6778554ac
+ 11d7d33017171bc2;
+ f1270485b203a3c1
+ c4c967c0a458cb94
+ 75e2e1a04e3ad3d7;
+ 8bdd409b687fa3a6
+ 827b480aa3a4c84c
+ e40958395d2015c9;
+ ef64f6c9b53bf8f9
+ 57f4b03cf43e8995
+ cc0ff0246e3ea756;
+ 7f9a3e8128f8743d
+ 16687b7bb8deb9bd
+ e7afa3631ceb1d83;
+ 205b70e04c091d20
+ 5cdad9e9a79b1abf
+ 295070cfdc2c3748;
+}
+
+gcm-mul96 {
+ cde4bef260d7bcda163547d3
+ 48b7551195e77022907dd1df
+ 4eec45fb8fc3b3e39aac7aae;
+ f7dac5c9941d26d0c6eb14ad
+ 568f86edd1dc9268eeee5332
+ 05134f056f51918c72e23289;
+ 85a6ed810c9b689daaa9060d
+ 2d4b6003062365b0a54364c7
+ bcfba16699cf54c7b4827b8c;
+ 6c160f11896c4794846ecfa1
+ 4a7130c9f137120634c95198
+ b831f2da94b112266bd6bc3e;
+ 48a877ff77bf79192a5b50ad
+ e5d9cd739a3d1f337f29549e
+ 5ad06fd826c670ca741020ec;
+ 6b0d27a4ba234085406a6136
+ 512061f7080cc07df0591d8f
+ e29fc44efee1497b3d29ef65;
+ a21f2dd88374d8cde8e160ad
+ 10997a21635c6d62c9269029
+ 5cc40a00243b31c565f37eba;
+ df3e6057acc87638f5080467
+ 33d9ff61cdbda3b3e9878731
+ dccd19797b205b612986e298;
+ ebfedd4705e505da1435dcea
+ a7b1cc49ae1d50c38201a894
+ e8be723b884eb9f69e388db1;
+ 476b3f102b752eb952953396
+ 6f27043eb621b7f65b000961
+ bc04044aaaef558b55e3dd7b;
+ 040ef2f9b2fc5fa450727a9b
+ 542cde52ebfda19d0ccc520f
+ de533f5f43678c1072d64ef8;
+ 215eb57bb3a4f3ebbbb18ac6
+ c95a97a48030370c33d090c5
+ 861b3f005e294a74ae9d78b5;
+ 4215abd6b3ad54efc9a38378
+ c5b93bf4f2aad2605faee2b0
+ bd3d716b1535654fc1336c3f;
+ 3fb648e27fff63102758fe2b
+ 69ac26afa3349829b9458630
+ 9199c9fc5fe891d9b22fe7c5;
+ 6fed54154f8f28523c03d4de
+ 1600157846b710ee72807a22
+ 66f5090ef7912cd1c4b4ebec;
+ 19bfb474fd71d891f24bb65d
+ 1563259f9eb53b571ea629c5
+ 11a1ad6bd0e17aa45aa29d18;
+ 4d57dd2d42f70800df9fcbac
+ a48b77dba189196d1ebba10b
+ 5887206626c27472a811261c;
+ 0467cb9fc2712a199e533fa9
+ 156308cdec3f768281e040a9
+ f6c50c86da0692784633b96a;
+ b9a222bd689aef66f5306ceb
+ 0c6b08ac8b0a22260c571b4a
+ 6b5169d0ead2cf118bead4a1;
+ 42bb8fdb233bfa6a5cfb0bad
+ 7d95214ade49cb3b6f5fe836
+ 23aeda3be39212e86bc0be3b;
+ 8131115c037ba323fe1dc815
+ 1784873f0eb5b647da6794c1
+ 711e6d0a1d2f28008b8c1ff1;
+ 8b5337685a96ed65b9aca338
+ 527ef19b09c063c46f88de9f
+ 5fcf403f2c1cbd40c5a2b2bf;
+ d41e72d7b97e23e6eabdff3b
+ cd211499268878dbf30f1dad
+ 8f025a46e6a1c48a74cad7a4;
+ 89d4b9b12012e4713df46795
+ 630e7952d22bb02d7100b8b6
+ e147d342d3feee155226d69b;
+ 49377d20a8f083455b663e4e
+ e1315f3c8f2aebfa921451dc
+ bd0327387c43f688f66cdbbe;
+ d1af5813b70d30ce2f1fef6e
+ f315d0798391805da08da3ae
+ 08fa0a0c901d0d0965968170;
+ fc5f8584b7c5e617669c0f16
+ e39815d4e9cfce3ed1ecdf3d
+ 98add0390bd310fa096f453f;
+ 264a7f16cb16c2e815f422cd
+ f0c8e30308be3c31e6bc58c0
+ cd186496b610dd8764aa152d;
+ b7cadcb658b970e47479a684
+ b5aefa69a4cd52147ed12ca9
+ c2de0b36d4dea7af5bbaf035;
+ 86981a874498ad0abef8bc4f
+ cb70e27e98ef1f0446b42fb1
+ 9d2ab48640b402ade690ca33;
+ 44d44b6d00f06dc188d472a7
+ 84e0c6f21195a3b9f4ae9855
+ 6c5c40b6a299efd5663d5010;
+ 11265febd11c164720eef9eb
+ 1c8dd0b00951f284649016ed
+ 3c0b6a72988abb596a30e347;
+ 00456331854bc78bf43966eb
+ 0cfa9138ddc39908445608fe
+ 7e180f9395090b8646d62aa4;
+ 95e81c2533e31c9c1a9851bc
+ 2810d858cbbc8424d126b807
+ 78ae33d19f5d9ba3b2158f0a;
+ e6daa089c3f9099c5ffb8241
+ 73d7634c04226f30cbb7f0e4
+ 922a3fa3bb9704aa3cb0c627;
+ a973a8cd190107314717a774
+ 56f3ff669c732b58db8f48af
+ f5996b9d374f4174367ca998;
+ 65f7cc9e3fb90e1721b73037
+ 4ffc9bc597f56ccbb2f294b3
+ 799bda7e13675b504cc15d48;
+ 8766fc69f6a9f2c0945ffd50
+ 5003cc0cae9ce021a5f1fa4f
+ 62aaf766cc72b312acf6b867;
+ fa91544485f1a1258b2b9b8f
+ 0911e32d65cc1770a18cbfe6
+ 5fe1f589f40181cef0aeaf9b;
+ effd1ff6778554acf1270485
+ b203a3c1c4c967c0a458cb94
+ 8847d0b844fc9063ff111626;
+ 8bdd409b687fa3a6827b480a
+ a3a4c84cef64f6c9b53bf8f9
+ 1b937802f75d4ebc4f3d7a86;
+ 57f4b03cf43e89957f9a3e81
+ 28f8743d16687b7bb8deb9bd
+ a53eb13d45700a7885120b81;
+ 205b70e04c091d205cdad9e9
+ a79b1abf91b0851e5ca605ac
+ d448d6ac6e6eb01171b14634;
+ 8451399587011677508a15dd
+ e524af3e2bee0646541a42c2
+ dab29efd14f77990ca5d724a;
+ ecccb44d65bad397abfaf529
+ ee41cf9a05c7efedef340153
+ fea1ab4c3083794c01303a23;
+ 9c51d2a90bbf7f1bfc338ab0
+ ef5746ea8fdcccd213e33f7e
+ 74b7906ccadf56726f06016c;
+ 8a5718fd25014107c8e7d715
+ a92add9589d1f5c054b2d983
+ 20656261ca5136c2bf69b1d1;
+ 514605ec590294a319b98020
+ 68a9f891bc5ba5afabf8c312
+ 55d0d749027044ab80ecfb46;
+ 2d12d7ff3c41122d70d17d45
+ 69eaff59a332ba58d5d5589b
+ a4de245c51057e4ca49e06d7;
+ fe079753ee1a957eb6d6699e
+ 6b7ea2725cb2dac07ecde957
+ ad498f1966703fd2cbad5b6d;
+ 59ac46fee6dda7abc8ad68da
+ ac90cfe22d2f1f2968cc42fa
+ f415976427d6fe6ff4547d08;
+ 8b669ed3bb3542a9cf44bbc8
+ c6254d980398bd94e66eb456
+ afe3c9c5ded2010edc99564f;
+ 3d405e51881e99027b8ab9ae
+ a3ccf860b0009740763d9683
+ 1ee6d3bc94ea166843327955;
+ 6c5f87b95460938de1288c69
+ d80ea12ff4bb5f069b8a2e86
+ 046ba565c8674b84f22ac9a3;
+ 041c1b9fc214e9ca2186ddf1
+ f6a7a3aa7e740da967828e36
+ 9c0b170f7e8ca9958dcfc12f;
+ 04b35b15ffaa6c36800d9645
+ 563a308ba60076817523bd2a
+ cff407868fb153b9b51fface;
+ bf1261b089d8f23a9c283507
+ 6a23faac2cdd67771cc667a8
+ 7006da38a1cf3992ef37b338;
+ 331f0a170b66283e4f834a06
+ 148f302c3973accd56f6f24e
+ d493d3e118362ffe57ffce5a;
+ 33958b8c2e2352fd61e4fa8f
+ ec816ac861a8b33779f09e7a
+ f700eeecf80cfd35a7c249c8;
+ 10fc02a8f48afa3080ee119a
+ 52a9a817e4f2b94b0820cab3
+ 41f9bc5aceef5e3c164829d6;
+ 83a8cffeea7c486315799dc8
+ 75fba578c8ec4837898a9214
+ 9ab99439ea7108fdd2b3a68a;
+ 2b5b0677da1ac273117b45bc
+ fff5d5f8b6fde2893232a9f8
+ ed9e4c863cac39665c322566;
+ 1d14517ffae475f6b94a43a6
+ 7b3d380d2f9aaafe2dd721c0
+ a84bebd2a47410cb5320cd55;
+ 095c8808847689211450ba80
+ 95ffab1eaadf66fd22ac1976
+ 09742e21f274088ba0c8fcc0;
+}
+
+gcm-mul128 {
+ cde4bef260d7bcda163547d348b75511
+ 95e77022907dd1dff7dac5c9941d26d0
+ ae22821f55ada6b996c3818891f4ec1d;
+ c6eb14ad568f86edd1dc9268eeee5332
+ 85a6ed810c9b689daaa9060d2d4b6003
+ c23e2072f3dbef54a6d43f840a45cd25;
+ 062365b0a54364c76c160f11896c4794
+ 846ecfa14a7130c9f137120634c95198
+ e4c3bf75dfae8f6201d306bb612d2757;
+ 48a877ff77bf79192a5b50ade5d9cd73
+ 9a3d1f337f29549e6b0d27a4ba234085
+ b5e1c1885725019124e64e12a7f7a284;
+ 406a6136512061f7080cc07df0591d8f
+ a21f2dd88374d8cde8e160ad10997a21
+ 83dc338673e6dce375f0c9e9c3853a3f;
+ 635c6d62c9269029df3e6057acc87638
+ f508046733d9ff61cdbda3b3e9878731
+ 48660987fa15f010812e499b7e448508;
+ ebfedd4705e505da1435dceaa7b1cc49
+ ae1d50c38201a894476b3f102b752eb9
+ 1be7a7b553d5f4e88c6bdda1162fc56b;
+ 529533966f27043eb621b7f65b000961
+ 040ef2f9b2fc5fa450727a9b542cde52
+ 7c48e4ab5e27e4f79f7c02e4e171cc2b;
+ ebfda19d0ccc520f215eb57bb3a4f3eb
+ bbb18ac6c95a97a48030370c33d090c5
+ 45d12390797c08a0c3cc9244cd56b922;
+ 4215abd6b3ad54efc9a38378c5b93bf4
+ f2aad2605faee2b03fb648e27fff6310
+ c53ccfdb25d06cd49acea8481c953bb7;
+ 2758fe2b69ac26afa3349829b9458630
+ 6fed54154f8f28523c03d4de16001578
+ 413a6503df527330e38a5e62d61677da;
+ 46b710ee72807a2219bfb474fd71d891
+ f24bb65d1563259f9eb53b571ea629c5
+ 4c22f463e2528bfff499d3337d32a921;
+ 4d57dd2d42f70800df9fcbaca48b77db
+ a189196d1ebba10b0467cb9fc2712a19
+ 068a3e3a1cf5552b90d915e565c76c47;
+ 9e533fa9156308cdec3f768281e040a9
+ b9a222bd689aef66f5306ceb0c6b08ac
+ 1463b22c7b22f4b483ceff293a405c18;
+ 8b0a22260c571b4a42bb8fdb233bfa6a
+ 5cfb0bad7d95214ade49cb3b6f5fe836
+ d1be35fea22f3168cb22d7b044c4a53b;
+ 8131115c037ba323fe1dc8151784873f
+ 0eb5b647da6794c18b5337685a96ed65
+ 39ee791290bd770cc3747c82e906de45;
+ b9aca338527ef19b09c063c46f88de9f
+ d41e72d7b97e23e6eabdff3bcd211499
+ 5e39550b65471a1a5a8db0a1a36ba3a6;
+ 268878dbf30f1dad89d4b9b12012e471
+ 3df46795630e7952d22bb02d7100b8b6
+ f1f7219c57aca09072abd1a4b5dc211c;
+ 49377d20a8f083455b663e4ee1315f3c
+ 8f2aebfa921451dcd1af5813b70d30ce
+ c53ec2fa18d6dd8749295e7246056537;
+ 2f1fef6ef315d0798391805da08da3ae
+ fc5f8584b7c5e617669c0f16e39815d4
+ ba9f8b1bbaaca05549621835352a0732;
+ e9cfce3ed1ecdf3d264a7f16cb16c2e8
+ 15f422cdf0c8e30308be3c31e6bc58c0
+ e24b90e7ca7ee0094901641a6ed9efe3;
+ b7cadcb658b970e47479a684b5aefa69
+ a4cd52147ed12ca986981a874498ad0a
+ 6a8831e02852976a844c69f551cd6617;
+ bef8bc4fcb70e27e98ef1f0446b42fb1
+ 44d44b6d00f06dc188d472a784e0c6f2
+ d8ede7cda85607c85ca2aa454275cab5;
+ 1195a3b9f4ae985511265febd11c1647
+ 20eef9eb1c8dd0b00951f284649016ed
+ b7690610ba96abfaa395dc709830c17d;
+ 00456331854bc78bf43966eb0cfa9138
+ ddc39908445608fe95e81c2533e31c9c
+ 7b23455563491e6234d7f3976ed92534;
+ 1a9851bc2810d858cbbc8424d126b807
+ e6daa089c3f9099c5ffb824173d7634c
+ 4111b410f25d6c27ef36e4c0744e06dd;
+ 04226f30cbb7f0e4a973a8cd19010731
+ 4717a77456f3ff669c732b58db8f48af
+ f3ed8ac5133b62dc453bb3b845371f07;
+ 65f7cc9e3fb90e1721b730374ffc9bc5
+ 97f56ccbb2f294b38766fc69f6a9f2c0
+ 97bd7eac33021557df0c54ca9b45c4b3;
+ 945ffd505003cc0cae9ce021a5f1fa4f
+ fa91544485f1a1258b2b9b8f0911e32d
+ 074736b8f03cfe2d058b60a60c1c42b2;
+ 65cc1770a18cbfe6effd1ff6778554ac
+ f1270485b203a3c1c4c967c0a458cb94
+ e6159e8e83f7acbcd6e3c1530ec97a31;
+ 8bdd409b687fa3a6827b480aa3a4c84c
+ ef64f6c9b53bf8f957f4b03cf43e8995
+ 47c1e7905f2f87b6a522a2eb83b6e7cd;
+ 7f9a3e8128f8743d16687b7bb8deb9bd
+ 205b70e04c091d205cdad9e9a79b1abf
+ 48d09e17f51f54cb44113d4f22d19bee;
+ 91b0851e5ca605ac8451399587011677
+ 508a15dde524af3e2bee0646541a42c2
+ 7b880e45b35f9b942de7b817ad2d3921;
+ ecccb44d65bad397abfaf529ee41cf9a
+ 05c7efedef3401539c51d2a90bbf7f1b
+ 0f092a20ab3a445fa314921920e68a7b;
+ fc338ab0ef5746ea8fdcccd213e33f7e
+ 8a5718fd25014107c8e7d715a92add95
+ b03bdb56bcea03d7a98444d06c4d9949;
+ 89d1f5c054b2d983514605ec590294a3
+ 19b9802068a9f891bc5ba5afabf8c312
+ 7c950c3817abf217b1bb67c78dbc9ce1;
+ 2d12d7ff3c41122d70d17d4569eaff59
+ a332ba58d5d5589bfe079753ee1a957e
+ 22164f3d69c20fb9a211645810a980b5;
+ b6d6699e6b7ea2725cb2dac07ecde957
+ 59ac46fee6dda7abc8ad68daac90cfe2
+ f916129ec57c478ffd99077e76fb9f0b;
+ 2d2f1f2968cc42fa8b669ed3bb3542a9
+ cf44bbc8c6254d980398bd94e66eb456
+ ccacc0839b857afecba7bbd5ca6b2e2c;
+ 3d405e51881e99027b8ab9aea3ccf860
+ b0009740763d96836c5f87b95460938d
+ b5dc31fc7ae8d1a7c4b638fa22490910;
+ e1288c69d80ea12ff4bb5f069b8a2e86
+ 041c1b9fc214e9ca2186ddf1f6a7a3aa
+ 9445b9b898beeb32a4d1ce0ab979c740;
+ 7e740da967828e3604b35b15ffaa6c36
+ 800d9645563a308ba60076817523bd2a
+ 765a9b5e6dd62f8b3bba62382a58f149;
+ bf1261b089d8f23a9c2835076a23faac
+ 2cdd67771cc667a8331f0a170b66283e
+ 7ae006a4c122e24d4f7e3ff2c6f1354d;
+ 4f834a06148f302c3973accd56f6f24e
+ 33958b8c2e2352fd61e4fa8fec816ac8
+ 2935d8d91408993ddb7a7d0d8db8516a;
+ 61a8b33779f09e7a10fc02a8f48afa30
+ 80ee119a52a9a817e4f2b94b0820cab3
+ ae4fd2f3a8d384e0b395461a8e326022;
+ 83a8cffeea7c486315799dc875fba578
+ c8ec4837898a92142b5b0677da1ac273
+ 9b0c75856b1c2972cb990106690d373b;
+ 117b45bcfff5d5f8b6fde2893232a9f8
+ 1d14517ffae475f6b94a43a67b3d380d
+ 5b7b6a4fdfcf0c8a6d67f240458b70f3;
+ 2f9aaafe2dd721c0095c880884768921
+ 1450ba8095ffab1eaadf66fd22ac1976
+ 729752ad6453d80b3d31e7433be19add;
+ 063e113ab61f813e28a1397a7974a1d7
+ f4220c785fe426a5a0e80f678d404147
+ dc51774484281b3ab9cd2859a1f91063;
+ 842941feeffdc2eb44dc8c0d5e8f444f
+ 7f4e0c893959b74dc23a7bb40e7e0013
+ 1a01406d34cf1da32e48b55e792b37e9;
+ e5150686d2301b43a15a84e81d7f5ced
+ aa49e2414ebf47970e560475cff20687
+ 0e9125c21526a8dc35085476ffbd523d;
+ 7de69146acc3ab6cf8556b7aa7769459
+ 48d1b8834df2196c92ec1718dcdeee0d
+ 31df775698abd477c7c389bbade1026b;
+ 52d9539726d2810391b3f9d10c39b07a
+ e8f08ce7cee4758a386a9943e97dedfb
+ 87800aad52281a95fb85fb4679774add;
+ e61e737882cd09c2b9a80f34c0fde11c
+ 2481b11fc76bfa4dbf710a9e544e0c53
+ a3b71ba7cd2e15c70cd5d40d6d145d1b;
+ 6ca1e040f9ad5b04140d98edabe08485
+ 290a4d87d13b07398a1458c2c6b61dbd
+ fdba17a43c6d190d2318855a2645748b;
+ bc1cccada8c1a0a9aabb6c4e3c3554f8
+ fb1ef61614c270295dfc0ca6551ca4bd
+ c7eabdcdea64775c683fa87614816b9e;
+ b75359f91cb9d921056b7de74fc9a9b3
+ 7154ce6c0b396179d31f06a1dd5982cb
+ a3fa226d9cd4183023e8061d3c3c7666;
+ c0d7cb23841da1ae8f4ae480cda98ad6
+ cf2bacf6f9fd3f821330c43f3df6c2b3
+ 635a20300e343fbd26211c9ff3ea26d5;
+ fac7cbcf96523d4723f91801325eb855
+ 3236651c96788d73d192ee53b3f3ebd6
+ 1ac40bd24b41dcc095e25dd6f5647d68;
+ 6ddd98cedbe88e245de25b1593b70f86
+ 01562d90a9b59ed034a867642d25d547
+ fe9b405f0a0e3d917075a2ce8282a881;
+ 56fa5c47f16f64b837bb4926214211a1
+ c696ba172010abb433922a22d9fd8815
+ 384b8bc7a4a1135a6bdf3c36756b0774;
+ 19165eb9d85197a21cc34ac0d5ae7be8
+ dbf98e4ffed2cf6b1372a5aa47b54fd9
+ 0b197a28af39b496a4d82db88cfa51b2;
+ d70c70e117bf1cae71b3a56f0e7d839e
+ a59cc783443d64f2ed6a29b96856beca
+ ab4ef17dac09d42ecaaac8d50643d89a;
+ 34fd6544bcf86b799e2a1681160ccf05
+ 5f0fd3001da597a1406d465b7b1419ea
+ c964db11b22df7e476eac1448500114e;
+}
+
+gcm-mul192 {
+ cde4bef260d7bcda163547d348b7551195e77022907dd1df
+ f7dac5c9941d26d0c6eb14ad568f86edd1dc9268eeee5332
+ 3bf1ea9b1ebee7e9444aaf08e585b09b31e67d3c95c9612d;
+ 85a6ed810c9b689daaa9060d2d4b6003062365b0a54364c7
+ 6c160f11896c4794846ecfa14a7130c9f137120634c95198
+ aa859fbc2a8ddcff234ac6e350b0e0c1a62f882f77219ce3;
+ 48a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e
+ 6b0d27a4ba234085406a6136512061f7080cc07df0591d8f
+ 6caddb90ad1aaf422acc28e99d650fa1a3d7b480101b3b32;
+ a21f2dd88374d8cde8e160ad10997a21635c6d62c9269029
+ df3e6057acc87638f508046733d9ff61cdbda3b3e9878731
+ f8d6b247d97ac3252c49a7544bbde8a0e45a999bc81b156b;
+ ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894
+ 476b3f102b752eb9529533966f27043eb621b7f65b000961
+ 27177d063a813ad4be51f4360cb3933bf6ccc1bb64c5cb32;
+ 040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f
+ 215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c5
+ c03117b28345bbbbdf657e220e2f23de46743a5591e66d69;
+ 4215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b0
+ 3fb648e27fff63102758fe2b69ac26afa3349829b9458630
+ 9c0ce16e01e9376fb28c571aa2401c7be69cabc249323ab4;
+ 6fed54154f8f28523c03d4de1600157846b710ee72807a22
+ 19bfb474fd71d891f24bb65d1563259f9eb53b571ea629c5
+ e869d24bde7293357bb17686c423591a891c40eb75e9cf8c;
+ 4d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b
+ 0467cb9fc2712a199e533fa9156308cdec3f768281e040a9
+ 26ca24fde1d3d37a5e3dc72acf6d2b31ab1d084caa3dc205;
+ b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a
+ 42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe836
+ ee889525ce4e6531e0eb218a0e72bdad13ecc5a1842d16f6;
+ 8131115c037ba323fe1dc8151784873f0eb5b647da6794c1
+ 8b5337685a96ed65b9aca338527ef19b09c063c46f88de9f
+ 12eeda395ce56e2170f6671f527f165f1992cc1940b552f7;
+ d41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad
+ 89d4b9b12012e4713df46795630e7952d22bb02d7100b8b6
+ 55153969c52056416bfd39a39cd2417339c800620227b450;
+ 49377d20a8f083455b663e4ee1315f3c8f2aebfa921451dc
+ d1af5813b70d30ce2f1fef6ef315d0798391805da08da3ae
+ 7e3e26d9c6514465ae7258f1ed4909c83ea1bbcb8a0b2947;
+ fc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d
+ 264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0
+ 8acad6c66a7d17fc4e55a164408cf9ad42974ee147d6fd0f;
+ b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca9
+ 86981a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb1
+ b62791c6430580b6921bda4e8f0dc67a3cd4c344ba87a56a;
+ 44d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae9855
+ 11265febd11c164720eef9eb1c8dd0b00951f284649016ed
+ 9a063e0f09a4fc2e41a63b38564fc07c578df43375a31c9b;
+ 00456331854bc78bf43966eb0cfa9138ddc39908445608fe
+ 95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807
+ 6eb9bc75eb709c4a6f63d8121d25b8777f5ea3af865ce812;
+ e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4
+ a973a8cd190107314717a77456f3ff669c732b58db8f48af
+ 0b3e51503a58f410adb27a6203a8966d47657d481a302d23;
+ 65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b3
+ 8766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4f
+ 82de8284669677b6832d83675af4fe5462636a530459d49a;
+ fa91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6
+ effd1ff6778554acf1270485b203a3c1c4c967c0a458cb94
+ 61d8b471ee449edb41627d254bfbfcbca10babbc1460d5f8;
+ 8bdd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f9
+ 57f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd
+ 254a831b866aad0f5e51943fc70c5ccaa7b9adba85762f00;
+ 205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac
+ 8451399587011677508a15dde524af3e2bee0646541a42c2
+ 418f551166e166e2e89fdc3d3a7a1e60e50e472c349da9de;
+ ecccb44d65bad397abfaf529ee41cf9a05c7efedef340153
+ 9c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e
+ ecf94369195385ea66741348bd0e796c461293ad8b1d1895;
+ 8a5718fd25014107c8e7d715a92add9589d1f5c054b2d983
+ 514605ec590294a319b9802068a9f891bc5ba5afabf8c312
+ 245f715f907f93b9b5277b55f844f5b4aa732ac698a76f95;
+ 2d12d7ff3c41122d70d17d4569eaff59a332ba58d5d5589b
+ fe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde957
+ 233a36249df31b12a3da455a1ff4c34f457399aa9ae8194c;
+ 59ac46fee6dda7abc8ad68daac90cfe22d2f1f2968cc42fa
+ 8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb456
+ db7a3e16e9aafeab616ce0fd985073f9eefbcb08c69985b7;
+ 3d405e51881e99027b8ab9aea3ccf860b0009740763d9683
+ 6c5f87b95460938de1288c69d80ea12ff4bb5f069b8a2e86
+ 7fc4a6d0b794e1bc893a00969479168876f166d1140aa9e7;
+ 041c1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e36
+ 04b35b15ffaa6c36800d9645563a308ba60076817523bd2a
+ da67471cfae7c99a25eb0f23d5081e6f05888ef4c7c5651a;
+ bf1261b089d8f23a9c2835076a23faac2cdd67771cc667a8
+ 331f0a170b66283e4f834a06148f302c3973accd56f6f24e
+ 6a391d4b0a662c09d3807c90dfcb8f230e260dacb89943e0;
+ 33958b8c2e2352fd61e4fa8fec816ac861a8b33779f09e7a
+ 10fc02a8f48afa3080ee119a52a9a817e4f2b94b0820cab3
+ 8ae8f405accb95e13d86bed19e63f6d6efe47264a46960ca;
+ 83a8cffeea7c486315799dc875fba578c8ec4837898a9214
+ 2b5b0677da1ac273117b45bcfff5d5f8b6fde2893232a9f8
+ 72892f188dce0da69ee68b3782ead0d40f1748fbec7dfd06;
+ 1d14517ffae475f6b94a43a67b3d380d2f9aaafe2dd721c0
+ 095c8808847689211450ba8095ffab1eaadf66fd22ac1976
+ 281ef0eff8afd5233318b564c8ed228e76c075ba61e7bd6b;
+ 063e113ab61f813e28a1397a7974a1d7f4220c785fe426a5
+ a0e80f678d404147842941feeffdc2eb44dc8c0d5e8f444f
+ 4fa4ca4d35e133d9d94815fc1bd294792bf73d2cb470eef3;
+ 7f4e0c893959b74dc23a7bb40e7e0013e5150686d2301b43
+ a15a84e81d7f5cedaa49e2414ebf47970e560475cff20687
+ 9d7c763547460f559d2ace4bc185f365e0c634e9ddffe0fd;
+ 7de69146acc3ab6cf8556b7aa776945948d1b8834df2196c
+ 92ec1718dcdeee0d52d9539726d2810391b3f9d10c39b07a
+ 33c5a1a6645c8ea5e2a1bd5c3d8a05ed1fbf25bc16b969b1;
+ e8f08ce7cee4758a386a9943e97dedfbe61e737882cd09c2
+ b9a80f34c0fde11c2481b11fc76bfa4dbf710a9e544e0c53
+ 14ed2a6864c16b031fe425f0edd51930c4e09a1672e28578;
+ 6ca1e040f9ad5b04140d98edabe08485290a4d87d13b0739
+ 8a1458c2c6b61dbdbc1cccada8c1a0a9aabb6c4e3c3554f8
+ ae886c5aa093d9c66b6de64062eccf3c5d2c3fb763bdde09;
+ fb1ef61614c270295dfc0ca6551ca4bdb75359f91cb9d921
+ 056b7de74fc9a9b37154ce6c0b396179d31f06a1dd5982cb
+ 877d80fe26e43415303f4590f934354f265aefc3aa7bf85c;
+ c0d7cb23841da1ae8f4ae480cda98ad6cf2bacf6f9fd3f82
+ 1330c43f3df6c2b3fac7cbcf96523d4723f91801325eb855
+ 9ffdb8a099964dd83b1936e57a1c3511c92c68e0c712d1ba;
+ 3236651c96788d73d192ee53b3f3ebd66ddd98cedbe88e24
+ 5de25b1593b70f8601562d90a9b59ed034a867642d25d547
+ 6bd995f6829d0ac4d313f7ab100ea03ffbac19de700dce3a;
+ 56fa5c47f16f64b837bb4926214211a1c696ba172010abb4
+ 33922a22d9fd881519165eb9d85197a21cc34ac0d5ae7be8
+ 1fbdf165adb07f53ff3ea39a33a82ab9a5cb243259c5ec1d;
+ dbf98e4ffed2cf6b1372a5aa47b54fd9d70c70e117bf1cae
+ 71b3a56f0e7d839ea59cc783443d64f2ed6a29b96856beca
+ 14c2eb66e8aa8bdcd09978ebcb905473a8edff6c771da7f1;
+ 34fd6544bcf86b799e2a1681160ccf055f0fd3001da597a1
+ 406d465b7b1419ea51cf858f938f6daafbd656445a09898e
+ c1f403fe552c5a3d008512eb2d015705e149072ce1d3e69a;
+ aa96ffc3d1d2e31e4e34c94b8bfae64825ecd75a66d88eed
+ b969ffe07669845ebb7a24c69f13d099f47166edf54538e8
+ a033fe30ee8714a173e1fd5c821ff2c5aeaeda27c3a9dcca;
+ 8fbf433a7ff212085179e79771f6eee7283ab178ef2b800d
+ 7b969da05780ffc1ba78c70dda7a4ca2a25e771702fb1901
+ ecff14eb486025a840e4b7d8b43075a87de1cac31cf05804;
+ ecfc8a959cb8e75079bb018ccc8c54f31b450e88f8e90029
+ 26ad0284c738f4cb0f58a1e34c8b15ad930c1b627235a2cb
+ 936b458a28fc0c6de0ea6f10e49cc13892899a112fa175b4;
+ 84241986c251f5b70be2367f047265264e0da72efe8995e6
+ c932a17eab511eddb8e4ba463c663035a6ae8a7a899e4279
+ c106ea40f0e1a1cab89dfd44d27bec7ad878e4bfdefb1c8a;
+ d54d03f0e0f3e961dcfd40088d5be74088e4097efb0368c7
+ e2f431ee6988cf2a0e9ebeb3de79c4f86c9e4fba61339d6d
+ 5962497cc337df2622d05213a1d8a5048ad7f017cc53b01e;
+ 907eab7707ca48ff5ba1ae93d16225d469de5747bc1addf5
+ 748729720a320fe14fd29cfc59314fe2079c0a2535ded561
+ cec57ed2e38528db38facc00e2cc658f681f371ccd55af54;
+ 12d6e3d33dcf7c71cd7d130323794e3da84a9df69703a9ca
+ f02d2a8f57ac71e554a6850d55882f8c7ae6994fc8528bd1
+ d4186ea94ce6b6e90797ce6c5c09a2f136e758b7bbc332a0;
+ 8c374fc43581d2f72a89584a2404a059f7f99c7241a0c879
+ d6d4455b382a9ce757b3e7a1d07585ad9d7ea9c7c9cf54f3
+ 55dc606dc9bad711515603b589f1e1227c03826c0d017b3d;
+ bc6d94238ab56d738e02abd651477cd726d6f3ebcd6fadea
+ b50906642a7de6496247060e7be3632ed9bd94bb42f45a87
+ 97ef18739ec98e9cff77ca3f323b567df45c8ca5e5f3b310;
+ 33b2cd2df9d1d905cfdb29983050d6bcdb686a0c897031ad
+ 09a5b8fa687ec3bad8e18dc2ad361f1e226e78876cd35f86
+ 5671fca885dd004ba927253cd0342c5e0bfbdaddc608dcd0;
+ c639733c5cd84aed8aaebabb7e0f24edfd9710b7bca91b61
+ 2ea37fc5cc09f7f62f66b423fcd2dec5de24d264f2c83983
+ e587e42c1e61c6ceadea37c68bfb715e01a15c47730ac81b;
+ 9c1b06319f687dbc68d9f07fd41ccb4f8cde8de201ec2680
+ 332bbded4883deea0b58b54bdd13c17ef292b0ded3caeb5e
+ 87aa1604b5d3a8bc2b6b8bc67d37a3dbfc3d12b19cbc43ae;
+ 57fd21df10bc6186265ee6ea45907de6cb822fb2ef953aea
+ 358a03e0fce2e1b9511bd332c86e67f123377a8f0256b8dc
+ 9e06e282ca2a9286bedf70783876f36cc238cca76cf81dab;
+ c73ae1b3c6cd3f104e3cb24284cfed17811d64d492d39ea7
+ 496993a25b072945d83f923e66b0a6689cf0969c003a8fca
+ 54ce4a46639bb8b1627fcb98bb76270c615f5a4411c8c754;
+ 80e322a4b1bf050c1220450433efb6b6d8a2d820cf27a64b
+ 9d47f636845dac557bb3e75f3a18fb8e173416867fcd0ee7
+ 0b77cb7790f367b2b8465ddec635b6d272e78c5f8670dab0;
+ 8ddd9236beec76d55ed58b10f91d07a037791ab96e83c4bf
+ 2fb5b205e592c172a5cbc19456c95c1bea6079f3867e52d6
+ 3dbca1bf0639237a10ee151674812fb5a4459614d405ea17;
+ 63cb3884b2a0a8ff825df752423f3179bfeb89eca385f20d
+ dce5f1f23564672e370ffc37d400a31e8aac1d426ce10df7
+ 3186bd4e2bd9b82499779406fa93fe98d2d74a9de4f94cfe;
+ 3c5ee478b3b63d91024780e974a8a2a0e7a36f84ab1286b6
+ 27e7d01b38a84a6de738721ed80fd0d7f69fa658abb5a440
+ 83f9caa8826f361ae7b7015fed42ed61d964258e4b9aa944;
+ d304128719b541a9451cead18e4c61d93d1f8fcc53574427
+ 767396322b3bf7d02cec05093696cec07591ada462271b1d
+ a6cb63d9b94d2269e85bb551f019180b8daaf1461946a2f1;
+ 1519eedde0df37a330fe8c22ebd77705917b7e32ae88f45a
+ 34a8ba3037235e19a394be4d26ce47317d8087684456b4cf
+ 25e012b33b54bb9734315020b02651a8476dd2af54fa9e39;
+ c5555e925e3e7b2ebc829b2d0505ea617b0ca9531bcdb960
+ 40d39040e632d562643ccb64286303040fcaf679e914eadd
+ b059b9be9e7700024accda083f56f569ac51e624ed72a7ed;
+}
+
+gcm-mul256 {
+ cde4bef260d7bcda163547d348b7551195e77022907dd1dff7dac5c9941d26d0
+ c6eb14ad568f86edd1dc9268eeee533285a6ed810c9b689daaa9060d2d4b6003
+ 789615a0602ce0d6e57a94074e22645fcdca1c2530cdce6a3a9898eefa48f602;
+ 062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c95198
+ 48a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085
+ ccd7a63e0f43d900d461f137b5f9a1b797580961dfe96d9e85ce0cc154f608ee;
+ 406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21
+ 635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731
+ 5f81e704e9b04d5b517392c372c5d2756eacc4f7a9442ac98d4bf8bb8536fe89;
+ ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9
+ 529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52
+ 094e95ea9c8346285f98c6f07ddd15830aa193170953a8abc41712732c76c336;
+ ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c5
+ 4215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff6310
+ 52d7772d1f860c1ce6cb4d1259577c2d43421ebfc44c89c43f05d0f424401b34;
+ 2758fe2b69ac26afa3349829b94586306fed54154f8f28523c03d4de16001578
+ 46b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c5
+ ad51dbcde8d0216bc998500d67317c852d273252d39d2c6a555d22a4fd180959;
+ 4d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a19
+ 9e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac
+ f25c5e462dc2a069bedb1d39ee68b16d025c0596ca27efd01c46555b245f6087;
+ 8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe836
+ 8131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65
+ 934d35daaec3791e39e799c81c62f07b1628bcd3113eecc4cc13993fad10e629;
+ b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499
+ 268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d7100b8b6
+ 99845195dba2f3b005653321a028907e11f546e597a641d652d85dae95e1775e;
+ 49377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce
+ 2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4
+ 16edc22df1c67d480ba3d471d61097eeba54e40ca0bf06d6fdd84232677efd19;
+ e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0
+ b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a874498ad0a
+ 49b59d9642e48bb2116b5b2515b77ba746e6ae804e8e9ed83ca2322a800a9ae6;
+ bef8bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f2
+ 1195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed
+ 6d03d43d9d7afc91f749c061d63dde21753f303c5d070e34dde5193c27e13046;
+ 00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c
+ 1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c
+ fd315ad2958b91405b2895b81391997c56a599609bdcd17ce9f2d540689374c1;
+ 04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af
+ 65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0
+ 4978b31536da1b90c44b6dfa1e874a37d4442a9e65979465998ae5ef0599fdfe;
+ 945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d
+ 65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967c0a458cb94
+ d64e275582ac14f23502aa43a0c2819e236e28770d72f3e9fe0d91b1cfe18d2d;
+ 8bdd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e8995
+ 7f9a3e8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf
+ 32223b066ce69f5963af0f7e121424ad3ab03d818562327eb0a495e7b0a0a844;
+ 91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2
+ ecccb44d65bad397abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf7f1b
+ 98abd767205b0f7fe21909f48b6182430169836df1712981bc1ae96b4e5c1b2b;
+ fc338ab0ef5746ea8fdcccd213e33f7e8a5718fd25014107c8e7d715a92add95
+ 89d1f5c054b2d983514605ec590294a319b9802068a9f891bc5ba5afabf8c312
+ 35446e8c959e35b74ff4e8960a1c80c3a4fc60998fc074d3fa6d73e7787b2bdc;
+ 2d12d7ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe079753ee1a957e
+ b6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68daac90cfe2
+ b893278872133d6ae9370dd0c1bf7e6990438ef83b012db8b4ac0197ee115ac1;
+ 2d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb456
+ 3d405e51881e99027b8ab9aea3ccf860b0009740763d96836c5f87b95460938d
+ b954c35b504dd99c3f95f2778ac8c69c9516eb5ecb279f01dca0cc5b1d33528f;
+ e1288c69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7a3aa
+ 7e740da967828e3604b35b15ffaa6c36800d9645563a308ba60076817523bd2a
+ a947b0e3b6d5caa39dd7899d60cc739b86a306c9de07b826efe14d1565ae933c;
+ bf1261b089d8f23a9c2835076a23faac2cdd67771cc667a8331f0a170b66283e
+ 4f834a06148f302c3973accd56f6f24e33958b8c2e2352fd61e4fa8fec816ac8
+ 93c8e6eb9eb2a085c0fe1e424c031d75e3cb3924e6636a3d0fbd97a9057b1497;
+ 61a8b33779f09e7a10fc02a8f48afa3080ee119a52a9a817e4f2b94b0820cab3
+ 83a8cffeea7c486315799dc875fba578c8ec4837898a92142b5b0677da1ac273
+ 1a9447bbcab0bf9fa9d4f97b44df070a91e73465559561cf07bf66f253b74839;
+ 117b45bcfff5d5f8b6fde2893232a9f81d14517ffae475f6b94a43a67b3d380d
+ 2f9aaafe2dd721c0095c8808847689211450ba8095ffab1eaadf66fd22ac1976
+ 19931b3731ce5cd2a6e0fd8db3528a01cf67f21c9f2b6536f617786536862f1b;
+ 063e113ab61f813e28a1397a7974a1d7f4220c785fe426a5a0e80f678d404147
+ 842941feeffdc2eb44dc8c0d5e8f444f7f4e0c893959b74dc23a7bb40e7e0013
+ 7814dc31116b923eff0567f1898f0dcfe5db31cea5f82d371c895b9cd0e1e626;
+ e5150686d2301b43a15a84e81d7f5cedaa49e2414ebf47970e560475cff20687
+ 7de69146acc3ab6cf8556b7aa776945948d1b8834df2196c92ec1718dcdeee0d
+ bf48e4fcb2685f89934fe3b4e1f093795e48c129192425f8d83df0a859982026;
+ 52d9539726d2810391b3f9d10c39b07ae8f08ce7cee4758a386a9943e97dedfb
+ e61e737882cd09c2b9a80f34c0fde11c2481b11fc76bfa4dbf710a9e544e0c53
+ 3c2f3e81bbfcfe08da13e35354b1bac0f0af0da35266c33c3a85c7cfa2ee849e;
+ 6ca1e040f9ad5b04140d98edabe08485290a4d87d13b07398a1458c2c6b61dbd
+ bc1cccada8c1a0a9aabb6c4e3c3554f8fb1ef61614c270295dfc0ca6551ca4bd
+ 975de7c5d90df79434ad560bfa1f2d3acb2bb268bad74a40f40dfb0b0cc55d80;
+ b75359f91cb9d921056b7de74fc9a9b37154ce6c0b396179d31f06a1dd5982cb
+ c0d7cb23841da1ae8f4ae480cda98ad6cf2bacf6f9fd3f821330c43f3df6c2b3
+ 778ec7881d07957cb956ee98b77f4771f0b354eee8ad6ed146dc9848bb4e5a15;
+ fac7cbcf96523d4723f91801325eb8553236651c96788d73d192ee53b3f3ebd6
+ 6ddd98cedbe88e245de25b1593b70f8601562d90a9b59ed034a867642d25d547
+ b41eff7927b5a1646b42fe8e7f3404366196b47be1d22a51819727a2987a12c5;
+ 56fa5c47f16f64b837bb4926214211a1c696ba172010abb433922a22d9fd8815
+ 19165eb9d85197a21cc34ac0d5ae7be8dbf98e4ffed2cf6b1372a5aa47b54fd9
+ eb4d497d39f0ccce56894c544b916a5a32aabb5e8470197389918e758cf5bcbc;
+ d70c70e117bf1cae71b3a56f0e7d839ea59cc783443d64f2ed6a29b96856beca
+ 34fd6544bcf86b799e2a1681160ccf055f0fd3001da597a1406d465b7b1419ea
+ ef9fd1957ea0125681170f801a2ff55cd40c11f1d8d03e28a47d07e530518d8f;
+ 51cf858f938f6daafbd656445a09898eaa96ffc3d1d2e31e4e34c94b8bfae648
+ 25ecd75a66d88eedb969ffe07669845ebb7a24c69f13d099f47166edf54538e8
+ b48119d50954fe55c7cb531c051c858b91a2cc0be497434ac06f1746d05200b1;
+ 8fbf433a7ff212085179e79771f6eee7283ab178ef2b800d7b969da05780ffc1
+ ba78c70dda7a4ca2a25e771702fb1901ecfc8a959cb8e75079bb018ccc8c54f3
+ 417db866feb0dc25af3bbff0a733e5220044c6933507f6d68d651a77b3371083;
+ 1b450e88f8e9002926ad0284c738f4cb0f58a1e34c8b15ad930c1b627235a2cb
+ 84241986c251f5b70be2367f047265264e0da72efe8995e6c932a17eab511edd
+ 2093bb7f7243f7d09835512229a449b3fcfbebc4f158d1f360d61dfa33aba949;
+ b8e4ba463c663035a6ae8a7a899e4279d54d03f0e0f3e961dcfd40088d5be740
+ 88e4097efb0368c7e2f431ee6988cf2a0e9ebeb3de79c4f86c9e4fba61339d6d
+ aadd61dcffddf277215a600d2a262375b40e8e8a00d2d1ee59d656ad63eca173;
+ 907eab7707ca48ff5ba1ae93d16225d469de5747bc1addf5748729720a320fe1
+ 4fd29cfc59314fe2079c0a2535ded56112d6e3d33dcf7c71cd7d130323794e3d
+ 1ddab3418f7c2e73138a161d9480144100ac8a8c453cea6cbda181416ce835c1;
+ a84a9df69703a9caf02d2a8f57ac71e554a6850d55882f8c7ae6994fc8528bd1
+ 8c374fc43581d2f72a89584a2404a059f7f99c7241a0c879d6d4455b382a9ce7
+ ac62a144b60cbcee96700e35a156c4ea04e8527600094b7c7c1fa57eb67c78c5;
+ 57b3e7a1d07585ad9d7ea9c7c9cf54f3bc6d94238ab56d738e02abd651477cd7
+ 26d6f3ebcd6fadeab50906642a7de6496247060e7be3632ed9bd94bb42f45a87
+ 6ac5d880e25effaad82da8efe77ed2245c9306d82e19c9b680b0a166b13db5cb;
+ 33b2cd2df9d1d905cfdb29983050d6bcdb686a0c897031ad09a5b8fa687ec3ba
+ d8e18dc2ad361f1e226e78876cd35f86c639733c5cd84aed8aaebabb7e0f24ed
+ 6bc8ad093f2148dc06ee942ce06a6b6c41ad4fb2ae796f9351df4d7829d0b759;
+ fd9710b7bca91b612ea37fc5cc09f7f62f66b423fcd2dec5de24d264f2c83983
+ 9c1b06319f687dbc68d9f07fd41ccb4f8cde8de201ec2680332bbded4883deea
+ 7cdba7c767a1b2e0d8ea98db6d05d0e6dc5ec4add6d68cb3a0ed213ba91fb46f;
+ 0b58b54bdd13c17ef292b0ded3caeb5e57fd21df10bc6186265ee6ea45907de6
+ cb822fb2ef953aea358a03e0fce2e1b9511bd332c86e67f123377a8f0256b8dc
+ 4d19278b4626808b203535680f24d55aa0bcf39b89221ccdceef29212f738776;
+ c73ae1b3c6cd3f104e3cb24284cfed17811d64d492d39ea7496993a25b072945
+ d83f923e66b0a6689cf0969c003a8fca80e322a4b1bf050c1220450433efb6b6
+ e82546a97e4d982315567afa93cc9cfbed1e6a9a553fb7209ac3c0c8a0f7d2a0;
+ d8a2d820cf27a64b9d47f636845dac557bb3e75f3a18fb8e173416867fcd0ee7
+ 8ddd9236beec76d55ed58b10f91d07a037791ab96e83c4bf2fb5b205e592c172
+ 550b3822df20109989c3ad201218184ea69c16e7efc41e9ae40d163565ea52e2;
+ a5cbc19456c95c1bea6079f3867e52d663cb3884b2a0a8ff825df752423f3179
+ bfeb89eca385f20ddce5f1f23564672e370ffc37d400a31e8aac1d426ce10df7
+ b35239f297beda780ccb0168fadd0708fe02a09e29566b3cea47f8f1932321e2;
+ 3c5ee478b3b63d91024780e974a8a2a0e7a36f84ab1286b627e7d01b38a84a6d
+ e738721ed80fd0d7f69fa658abb5a440d304128719b541a9451cead18e4c61d9
+ 5c8cae06450a234fd67621baf1be40de09a7ee05227b7cc527bfffb14c861641;
+ 3d1f8fcc53574427767396322b3bf7d02cec05093696cec07591ada462271b1d
+ 1519eedde0df37a330fe8c22ebd77705917b7e32ae88f45a34a8ba3037235e19
+ 0d07975a21745840a9528f6ad84812f76d981c7cbd51d23295b0a4c77647955a;
+ a394be4d26ce47317d8087684456b4cfc5555e925e3e7b2ebc829b2d0505ea61
+ 7b0ca9531bcdb96040d39040e632d562643ccb64286303040fcaf679e914eadd
+ b11034402f9178618471341a208717e0db49389cc10169da3bbfd18c0b155dbf;
+ c05af8843ce6a427b99a5dc266de31c09165237eeefe4b58cc034b9f099f0467
+ 8c2a9da898b39324cd3087a651014f6796f9c4881d89e127e62221e47e57badd
+ a3115e01610e03d14a9aa231f0af30c2f864724a9b827bee723862a2da21f67c;
+ 678d490c2f320ff8fb1c42761bd439f3e96dc0ed1d5b2169912af1a4e2c533c5
+ 2ba3e8c71c23a089e231480aa63c484fb34bd522397f102cb8ecf4f64e329884
+ f8fb5571f45bfe48a3e0a32c0152f4cf9f05fd9b6df1b16c135ac57b53140b1f;
+ fe73be257a753b38200bc23f94a079bde2dd98d813655dafa15b85419d15c41a
+ 5153cce5d0e8c8702db2ba11927589678d4f7b8fcfad4818c411f15f45230090
+ f0eb21d7c095cbb71ce2a6e98cd274161a006a321bc6516d92e292d4f9d80fe5;
+ 3874f9a532ee46496ae753a2340af7b91f9632fc5ae71ae18b40de751ab6b676
+ 1ca16434a9935e466e11c1cb072f32a59c313dba3db646ae909a096697d9a7b0
+ 2784404b966884dd1be5778471a98b8cd9ffc6fb4cef97e9f828f5a9976519ea;
+ 556463ff1126ebc43263391424d02739d0787e804d8f1dccf6c897a8a4843132
+ 4324041b5302ccd501b538bd03d5cb5c90d1fd3f7d2be187a787032c79ed9007
+ 7a286ff42bd536174d2d471c7edf52d76cc1e2149ae5e89fe7c527d1baf61024;
+ 64ee4ce1d3fc042c084f7d8c0c48ad7d6f1eabd0fd1ec24a88f26734d5c8d92d
+ bd873a8fe113090d401bea4d28ff49f10ff593adc258e091abd31b62dd173515
+ c4cf640c91c885ead4d5ad0de5769f1bf2fc7cc928ddb20ecd77903e78d60296;
+ 8f98765970acc6602da063aae01a2a199d3a4f37a5f062d216d2053a83b5d3a0
+ 488ab0d2df631b2892cdfcf9fdd0f37de9ed67179aeae82fe00009428b297b55
+ fd32af281c32754a7cb4b70f0856a6a595d53df2f655dfb5d065813b658f6e49;
+ 3230a6d917fa0c1a233c9ebc8a4cba45b20543c540fc1b9dbce078b87a1534ac
+ f03897b95a3f372e9f6c5a5f2ae44a7dbce9ba43a39089de20de70d0544b5151
+ d717a2d8e24c431d7322091c4afa9291e6b2f642164fb5dd41b03d63eb3991ad;
+ db0a16e9769e8f2fc12c7f839fab269a0056284a697ffd4113a1cf43b5d5bdce
+ 2d86dead83f5a356e9106bedf908db61f1119f9700260ea9379cc7232184d217
+ ad5a3798580a21a9af3a14a20c498e9ba81075c0d4c771481da0b3e6544bb711;
+ 158fee8ca42e75614739e9007f234fbcd86b0ad8f641a0449b6d9b0f99d1cb4a
+ 57a4d6f987feb0ade90aa1d81c4f497b3734be301da3e25fe692629db57311f4
+ feca63faa55407c1cbe7ba36da4101ed6fc318162d0834ef6ea91095e6fbb38c;
+ 22f3a1573f9e0553a23e96265e4326fa532d7136863e5b4bc6c99ade3d4eb23c
+ acdf6e42ad8ca13187eba1532920ba31582b3793b05fa65e9f80c5814b91f4d3
+ c9ddac65e7d93033570d39fc200ea11df6f56cf19994e791092cab78342f8793;
+ c581c7b16c46b484859c6d19eebaf124681aa3be9943307fa4ef095ef8e7e50b
+ 703dc0420e74227c9351366ef8e98e1e24b48aa989dbb8d0f10471ae5428a601
+ f1e437fdbee29a5838d58d6ca0abd51bf3fe4bed82ea86f5e3d2e8effa7dbee9;
+ 2fbe4f5cb2dab2863e574842cc0b3774e00dcfa63b0db1716c7e916a26fc2e19
+ 8f8db63ab59955989497782f16c5816270ef3fbe4ea22f484ddc12ec8f4bdbd6
+ c8721ce2f69e7d5d6fc5746fea4185ff8a7d296b99bcc17bbbad3e7036053bcb;
+ ebdfbafb21fcf5427dbee5f95b53a0b4cb6d7c128b79f4657895f4b0ba518dd6
+ 1436140f20d40224baac3a602da83cb254a7e03f052c63c1f3f00f301cc944a1
+ f3298d9cfbd5fd3a98e1ecabe8a2aac82b1b54f2f65f09d7cf3bcd9ca8bd2bcf;
+ 789133bb8048f07dc123f2ca7e20c83988e4bfea6d561ab5aea542db544a1437
+ 6d5d52f7265c7a8d2fc4feef99b9dba89eb472f71d8eb5affe900d776e4cf74e
+ 795de908ed1e3149d3e92fc4d2fb56c47db72b54097702f360c3de4363a1b38c;
+ 52b6c86db981143082735c6473a86a5da3d2e8cbb8602ebbaf08bf9315fba15f
+ 46714bfd2c8312fb5744dfe84615ddb93f15360161f2efb1fc39b8b6ad97427d
+ 9e96a1dd18f2683365cb98a46a9cb8bf49f1766ac86eddec4a87dfa3f83339ce;
+}
729a27ed8f5c3e8baf16560d14c90b43 d53fabbf94ff8b5f 1d0cb2af1654820a;
729a27ed8f5c3e8baf16560d14c90b43 df8c6fc637e3dad1 29358cc6c83828ae;
}
+
+idea-cmac {
+ e4bef260d7bcda163547d348b7551195
+ ""
+ 2a288096bbfd3366;
+ e77022907dd1dff7dac5c9941d26d0c6
+ eb
+ 2f7fb9948ff504c6;
+ 14ad568f86edd1dc9268eeee533285a6
+ ed810c9b689daaa9060d2d4b6003062365b0a54364c76c16
+ d077db9252901d26;
+ 0f11896c4794846ecfa14a7130c9f137
+ 120634c9519848a877ff77bf79192a5b50ade5
+ c17895f93dd73a8a;
+}
+
+idea-ccm {
+ e4bef260d7bcda163547d348b7551195
+ e77022
+ ""
+ ""
+ ""
+ 42939dba;
+ 907dd1dff7dac5c9941d26d0c6eb14ad
+ 568f86
+ ed
+ ""
+ ""
+ 3facc6db;
+ d1dc9268eeee533285a6ed810c9b689d
+ aaa906
+ ""
+ 0d
+ 7e
+ 4f9519dd;
+ 2d4b6003062365b0a54364c76c160f11
+ 896c479484
+ 6ecfa14a7130c9f137120634c9519848a877ff77bf79192a
+ 5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba23408540
+ 53683900f166af9bfd8a3e46e63e8e38af27b1c46816b6ae
+ 5e8bd4980b4efd9c;
+ 6a6136512061f7080cc07df0591d8fa2
+ 1f2dd88374
+ d8cde8e160ad10997a21635c6d62c9269029df
+ 3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e5
+ ea20e70bc5af22eece46f5b4adb9148a716a08fe014fd8e603cbad4b05
+ df275b1d8b433882;
+}
+
+idea-eax {
+ e4bef260d7bcda163547d348b7551195
+ ""
+ ""
+ ""
+ ""
+ 2ed1b711b35815fc;
+ e77022907dd1dff7dac5c9941d26d0c6
+ eb
+ ""
+ ""
+ ""
+ e16c2e8dcbe82476;
+ 14ad568f86edd1dc9268eeee533285a6
+ ""
+ ed
+ ""
+ ""
+ d71cbbb104ef47b6;
+ 810c9b689daaa9060d2d4b6003062365
+ ""
+ ""
+ b0
+ 93
+ f9fa771344725555;
+ a54364c76c160f11896c4794846ecfa1
+ 4a7130c9f1371206
+ 34c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f33
+ 7f29549e6b0d27a4ba234085406a6136512061f7080cc07d
+ cfcb5b76771f439b7e31a9503bc42213efcb50281711c0e0
+ e70f4193b0a49031;
+ f0591d8fa21f2dd88374d8cde8e160ad
+ 10997a21635c6d
+ 62c9269029df3e6057acc87638f508046733d9
+ ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50
+ dfd640ccfb02298e9bdb44464e210bb5039e2fcfdf99a07198b5a41744
+ 8100822295ddbb3c;
+}
+
+idea-gcm {
+ e4bef260d7bcda163547d348b7551195
+ ""
+ ""
+ ""
+ ""
+ b53b4af5791611f9;
+ e77022907dd1dff7dac5c9941d26d0c6
+ eb
+ ""
+ ""
+ ""
+ 5d33a50146fc1873;
+ 14ad568f86edd1dc9268eeee533285a6
+ ""
+ ed
+ ""
+ ""
+ 476a48223872d6dc;
+ 810c9b689daaa9060d2d4b6003062365
+ ""
+ ""
+ b0
+ d7
+ e7f3f045a67219ca;
+ a54364c76c160f11896c4794846ecfa1
+ 4a7130c9f1371206
+ 34c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f33
+ 7f29549e6b0d27a4ba234085406a6136512061f7080cc07d
+ 35242bf91114f81e19e23a3ac1ccd5a9d133f097e1e32358
+ d7871555c86f43c4;
+ f0591d8fa21f2dd88374d8cde8e160ad
+ 10997a21
+ 635c6d62c9269029df3e60
+ 57acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dcea
+ badb12a7460b5d77826a7f419823376c332f6816280031f04aaffa9b92ed8c83e9
+ ca45ffd7a56d9250;
+ a7b1cc49ae1d50c38201a894476b3f10
+ 2b752eb9529533
+ 966f27043eb621b7f65b000961040ef2f9b2fc
+ 5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18a
+ 8508e77f69eba79e7dd8b644ed31dba2f0eba90d09b1170ec17caf72ee
+ 6c86db8654126e19;
+}
+
+idea-ocb1 {
+ e4bef260d7bcda163547d348b7551195
+ e77022907dd1dff7
+ ""
+ ""
+ ""
+ 6c1f67d06c352235;
+ dac5c9941d26d0c6eb14ad568f86edd1
+ dc9268eeee533285
+ a6
+ ""
+ ""
+ 461d68824249a125;
+ ed810c9b689daaa9060d2d4b60030623
+ 65b0a54364c76c16
+ ""
+ 0f
+ a4
+ f29d06f84026383d;
+ 11896c4794846ecfa14a7130c9f13712
+ 0634c9519848a877
+ ""
+ ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27
+ 02d1b52db3743fe74199d2d47c7b9a5b40be540fd3305c63
+ 95db9f9e14cc4137;
+ a4ba234085406a6136512061f7080cc0
+ 7df0591d8fa21f2d
+ d88374d8cde8e160ad10997a21635c6d62c9269029df3e60
+ 57acc87638f508046733d9ff61cdbda3b3e9878731ebfedd
+ 16241a876ecaa1787050ae161dc95e08b3c9f3f32f4c28e6
+ 4c3a1cbf28420f74;
+ 4705e505da1435dceaa7b1cc49ae1d50
+ c38201a894476b3f
+ ""
+ 102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa4
+ fc37976d31a17e5c9184a761ade81acb146791248da7073854564e80e2
+ 69afdd038f3f443c;
+ 50727a9b542cde52ebfda19d0ccc520f
+ 215eb57bb3a4f3eb
+ bbb18ac6c95a97a48030370c33d090c54215ab
+ d6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff6310
+ ca23f10e82cad6a83e29296f3040d728e2c19d8a70da3c85bfd6392e83
+ 13a82d59cedb63ae;
+}
+
+idea-pmac1 {
+ e4bef260d7bcda163547d348b7551195
+ ""
+ 487cb8bbd49fdf9f;
+ e77022907dd1dff7dac5c9941d26d0c6
+ eb
+ 61e71d184211ae2e;
+ 14ad568f86edd1dc9268eeee533285a6
+ ed810c9b689daaa9060d2d4b6003062365b0a54364c76c16
+ 2a59b4037636f6e9;
+ 0f11896c4794846ecfa14a7130c9f137
+ 120634c9519848a877ff77bf79192a5b50ade5
+ 64b5b29952d302fd;
+}
+
+idea-ocb3 {
+ e4bef260d7bcda163547d348b7551195
+ e77022907dd1
+ ""
+ ""
+ ""
+ d4146d9749c5b4cc;
+ dff7dac5c9941d26d0c6eb14ad568f86
+ edd1dc9268ee
+ ee
+ ""
+ ""
+ 91344823fdca261a;
+ 533285a6ed810c9b689daaa9060d2d4b
+ 6003062365b0
+ ""
+ a5
+ 32
+ bd1e855f2cfab6a4;
+ 4364c76c160f11896c4794846ecfa14a
+ 7130c9
+ ""
+ f137120634c9519848a877ff77bf79192a5b50ade5d9cd73
+ 9de3e559bcf16005a54f07a11b791f0c87486d260cd04d40
+ 0f6c004bce2fdfa4;
+ 9a3d1f337f29549e6b0d27a4ba234085
+ 406a613651
+ 2061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10
+ 997a21635c6d62c9269029df3e6057acc87638f508046733
+ 07d9e965ec0f32d6ba5393c0504a9e274d18fbb31e705f7e
+ d1f5621c6fa3f2c9;
+ d9ff61cdbda3b3e9878731ebfedd4705
+ e505da1435dc
+ ""
+ eaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043e
+ a51612481f15245dfec7f8e1ffa9bc47788140faac776d8fce971d2d96
+ 2030845d5729cf4f;
+ b621b7f65b000961040ef2f9b2fc5fa4
+ 50727a9b542c
+ de52ebfda19d0ccc520f215eb57bb3a4f3ebbb
+ b18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b9
+ cb28e83ecdf27012219f655bf27bb37de417f09f4337a92bfe5feb3da2
+ cc56a222f733795e;
+}
+idea-ocb3-mct {
+ 16 81bc29159fbaf9aa;
+ 16 fb5ea26d7558;
+ 16 1749134c;
+}
--- /dev/null
+### Local tests for Mars.
+
+mars-cmac {
+ 60d7bcda163547d348b75511
+ ""
+ 35a1192271ad4f717fe9e5ce36550ccc;
+ 95e77022907dd1dff7dac5c9
+ 94
+ 79d05cda7236e8a9038a3e87d6dd590d;
+ 1d26d0c6eb14ad568f86edd1
+ dc9268eeee533285a6ed810c9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f1
+ 04093d618ec9a9f929abceba0ea5d6a5;
+ 37120634c9519848a877ff77
+ bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8f
+ 0436ec24f98dbf64019710d997ca79ad;
+ a21f2dd88374d8cde8e160ad10997a21635c6d62
+ ""
+ 51be3cd07c56c6f821f8261bbf55fa38;
+ c9269029df3e6057acc87638f508046733d9ff61
+ cd
+ c29104d9daa7eb4abadd817b6890df83;
+ bda3b3e9878731ebfedd4705e505da1435dceaa7
+ b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b54
+ 6b2daa274c101b703e7cca9de8608b13;
+ 2cde52ebfda19d0ccc520f215eb57bb3a4f3ebbb
+ b18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e2
+ de39e39bd3108b76ec6c4c68a923ecfc;
+ 7fff63102758fe2b
+ ""
+ db668c175219b873ce67bfee1bf797dc;
+ 69ac26afa3349829
+ b9
+ d8e6cec8197a0d3b02b973e0b8821048;
+ 4586306fed54154f
+ 8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42
+ 1fef4ac7afbf6a5b2e8c6eb271a6c73c;
+ f70800df9fcbaca4
+ 8b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66
+ bdc7b92cd3b6b1f19165fa1452144363;
+ f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b
+ ""
+ baf27c811850b45c6165fa5f28c558ea;
+ 6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65
+ b9
+ c838ff7ffa0b020de74cdf1bc6d9cb1b;
+ aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf3
+ 0f1dad89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa92
+ 3834f582405017c74df2a58f50896bbe;
+ 1451dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e61766
+ 9c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb6
+ 797407de4940048d366f408567a0b4ca;
+}
+
+mars-ccm {
+ 60d7bcda163547d348b75511
+ 95e77022907dd1dff7dac5
+ ""
+ ""
+ ""
+ d9863a89;
+ c9941d26d0c6eb14ad568f86
+ edd1dc9268eeee533285a6
+ ed
+ ""
+ ""
+ 291967b1;
+ 810c9b689daaa9060d2d4b60
+ 03062365b0a54364c76c16
+ ""
+ 0f
+ f7
+ b93f6b02;
+ 11896c4794846ecfa14a7130
+ c9f137120634c95198
+ 48a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8f
+ a21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731
+ 9828628579a7dd487f473888502c5c84369b7c3a4c760eca290e95d6ecc9f0eeff551a28e55ab8f07a3b3058263e6590
+ 232a8e27bf269e09d6ca6691858e03d3;
+ ebfedd4705e505da1435dcea
+ a7b1cc49ae1d50c382
+ 01a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52
+ ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605f
+ 983ddf84477174e42ff5e4d86e34a4dba2cda48b0d9cc34dca96cae438508ea257ae6e4d0f34e6c38612bc4044d30e3f44550b49eb
+ aece86043084433dff242601596ec036;
+ aee2b03fb648e27fff63102758fe2b69ac26afa3
+ 349829b94586306fed5415
+ ""
+ ""
+ ""
+ c9700d28;
+ 4f8f28523c03d4de1600157846b710ee72807a22
+ 19bfb474fd71d891f24bb6
+ 5d
+ ""
+ ""
+ 86ac2560;
+ 1563259f9eb53b571ea629c54d57dd2d42f70800
+ df9fcbaca48b77dba18919
+ ""
+ 6d
+ ce
+ 7396d0ff;
+ 1ebba10b0467cb9fc2712a199e533fa9156308cd
+ ec3f768281e040a9b9
+ a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe83681
+ 31115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c46f88de9fd4
+ 2e78ed36197ee0fbe02aaf850ca07cef75d83137dfa779a043f43ad6207cb71df53b3bc72ec31947217f1131f9a7219f
+ 38d70bb7304992be2073bd3ded9589ad;
+ 1e72d7b97e23e6eabdff3bcd211499268878dbf3
+ 0f1dad89d4b9b12012
+ e4713df46795630e7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1
+ af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16
+ 91a4428db21b6870c8bed64235a802123bebc572b852321902ffa4e1f9197eab5a4e2d6e37587f493a77dc78355556ecf4078f6963
+ 2ca5ad4c8de48446dacc9ef0f8ed8ac6;
+ c2e815f422cdf0c8
+ e30308be3c31e6bc58c0b7
+ ""
+ ""
+ ""
+ e55b1e3d;
+ cadcb658b970e474
+ 79a684b5aefa69a4cd5214
+ 7e
+ ""
+ ""
+ 8e9f4277;
+ d12ca986981a8744
+ 98ad0abef8bc4fcb70e27e
+ ""
+ 98
+ da
+ 94060c3c;
+ ef1f0446b42fb144
+ d44b6d00f06dc188d4
+ 72a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf439
+ 66eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb
+ a845f5b258e7b48dfbf165716b84ab9d44a6fb31ae2db3969ab9236937b52c81e38427414b61004125cd07ee50001947
+ 053ae04c909fb9c1202dc16d15d93890;
+ 824173d7634c0422
+ 6f30cbb7f0e4a973a8
+ cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f2
+ 94b38766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1f
+ 7bc1f6ba933f20ea05b7b6eeed69b99dfb31c21c77a46690e151e756c0af9555851d17700b27ac7d1104a4ce197bb4d3e5d596ed37
+ 5b81abd7dea2c26dfdb3dd4fbb3679c9;
+ f6778554acf1270485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b480aa3a4c8
+ 4cef64f6c9b53bf8f957f4
+ ""
+ ""
+ ""
+ 5702f7ae;
+ b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b
+ 1abf91b0851e5ca605ac84
+ 51
+ ""
+ ""
+ d5c802e3;
+ 399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397abfaf529ee41
+ cf9a05c7efedef3401539c
+ ""
+ 51
+ df
+ bf7584e3;
+ d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a5718fd25014107c8e7d715a92a
+ dd9589d1f5c054b2d9
+ 83514605ec590294a319b9802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70d17d4569eaff59a332ba58d5d558
+ 9bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68daac90cfe22d2f1f2968cc42
+ 332eb9ba36705464ae13b42c953572119f3bd26d623fe066fa9eb42a3aa5222fc7a39367b997e903b8471ded7b4e1250
+ b10fea22e3e1c7cbdf334e2e66986200;
+ fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4563d405e51881e99027b8ab9
+ aea3ccf860b0009740
+ 763d96836c5f87b95460938de1288c69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7a3
+ aa7e740da967828e3604b35b15ffaa6c36800d9645563a308ba60076817523bd2abf1261b089d8f23a9c2835076a23faac2cdd6777
+ 2efcfbce25279f45598c9d5dff6821a9b6bdea37fc7c376e8a65c0d6182392b15de9832a2477f5c446b3028872892061a213cd7f51
+ e44e2d82e160ef2cd7d28cb80fc74194;
+}
+
+mars-eax {
+ 60d7bcda163547d348b75511
+ ""
+ ""
+ ""
+ ""
+ 783e4c5710aa46926fa54c1810e7e73f;
+ 95e77022907dd1dff7dac5c9
+ 94
+ ""
+ ""
+ ""
+ 1f777486cbacb84834939cf4312ba37f;
+ 1d26d0c6eb14ad568f86edd1
+ ""
+ dc
+ ""
+ ""
+ ea4ee101b3dfc447826294eb9e188f93;
+ 9268eeee533285a6ed810c9b
+ ""
+ ""
+ 68
+ 32
+ 36ad1e9dd22bc536eaf6e1bf4148b92c;
+ 9daaa9060d2d4b6003062365
+ b0a54364c76c160f11896c4794846ecf
+ a14a7130c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a61
+ 36512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f50804
+ a2b79ebe3a643e16a26496a833169c430350296feff84ab5e97a837f27c1cebf042c077d8ea23697c1101fcd3880025e
+ 3e081ad4715f6b2ccf59ac6cbee3ecbf;
+ 6733d9ff61cdbda3b3e98787
+ 31ebfedd4705e505da1435dceaa7b1
+ cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450
+ 727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b9
+ e32192ca15a8b60348fbcad6bed31fec7d8930fb015efea33f827a691a245be1b056f237da85e63dd7f6948a583c5040b24eb76747
+ c69cdf6b68ff0b95fd49073f69b24673;
+ 3bf4f2aad2605faee2b03fb648e27fff63102758
+ ""
+ ""
+ ""
+ ""
+ 8197dfbcc4259667affb2610283f7cb5;
+ fe2b69ac26afa3349829b94586306fed54154f8f
+ 28
+ ""
+ ""
+ ""
+ 4365d2d730280b57ebdd628d574db279;
+ 523c03d4de1600157846b710ee72807a2219bfb4
+ ""
+ 74
+ ""
+ ""
+ 90f8bb6ae36b77e86acd862d626e3e8b;
+ fd71d891f24bb65d1563259f9eb53b571ea629c5
+ ""
+ ""
+ 4d
+ 4d
+ e0c975ce580afac6215a31f89ed849f5;
+ 57dd2d42f70800df9fcbaca48b77dba189196d1e
+ bba10b0467cb9fc2712a199e533fa915
+ 6308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d
+ 95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca33852
+ 68cd20e274b1dfc8045c4f1a2a862ae38adaf6f1b4d37a869e1ca4dce62cffab0e767e21b7980a7a6923a4e6036e261f
+ ab0fc228a30f96fc6af0af7ed3b2ca23;
+ 7ef19b09c063c46f88de9fd41e72d7b97e23e6ea
+ bdff3bcd211499268878dbf30f1dad
+ 89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aeb
+ fa921451dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d
+ 2d5f33737604edbff4256e1803d85fdf97b1d11755a7c54907279c926103ad6dfcd2a49bc8f09692af0225e58727302883110a1d9e
+ 66d2add5b20b0083fe707359e14b9a81;
+ 264a7f16cb16c2e8
+ ""
+ ""
+ ""
+ ""
+ bfd46275d139ade04b23701a58f03996;
+ 15f422cdf0c8e303
+ 08
+ ""
+ ""
+ ""
+ 70b1aefbf33858867e95f8420409cc5c;
+ be3c31e6bc58c0b7
+ ""
+ ca
+ ""
+ ""
+ 06ed7dfc19e244619a78291ebfe53e1e;
+ dcb658b970e47479
+ ""
+ ""
+ a6
+ b3
+ 50a2cbdf827bdd413fc402b1bd4d3cad;
+ 84b5aefa69a4cd52
+ 147ed12ca986981a874498ad0abef8bc
+ 4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9
+ eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851
+ 1717ca0fe9a9f844e7b875383fffb728907e4381ca81aaad7d07ae4559463a25e3eb4eddc2c1eb47ac009050404e125a
+ 54681d8a74c5240d91fedda335ba0106;
+ bc2810d858cbbc84
+ 24d126b807e6daa089c3f9099c5ffb
+ 824173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3f
+ b90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b
+ b49998808ffe0713f231dc44d5fefd7b091d037fa88a0b00fa7df49a9cb715fa11272ad859a1b6bcd40fa4a618d4b9694a98800fe1
+ cfb2cf5bd57a0bd2e0b6e4766c85ee66;
+ 9b8f0911e32d65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967c0a458
+ ""
+ ""
+ ""
+ ""
+ c182f7ff71663492c075606138691990;
+ cb948bdd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a
+ 3e
+ ""
+ ""
+ ""
+ bfd6579cd96ad44cd5202593235be036;
+ 8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605
+ ""
+ ac
+ ""
+ ""
+ b0aa4fd770b15ab6cf76338e9e4ffcc9;
+ 8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397abfaf529
+ ""
+ ""
+ ee
+ 1e
+ d1aa1cfbf63991b5a87719a436f3bc15;
+ 41cf9a05c7efedef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a
+ 5718fd25014107c8e7d715a92add9589
+ d1f5c054b2d983514605ec590294a319b9802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70d17d4569eaff59a3
+ 32ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68daac90cfe22d
+ 6c1092bfaaba31b04c5ce196bd217368bbcb33fabbee09d16cc36d6047594e2f33f6241828d17230e69561355af84d2b
+ 9adaf12e17b54bb121e92f5262a03d46;
+ 2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4563d405e5188
+ 1e99027b8ab9aea3ccf860b0009740
+ 763d96836c5f87b95460938de1288c69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7a3
+ aa7e740da967828e3604b35b15ffaa6c36800d9645563a308ba60076817523bd2abf1261b089d8f23a9c2835076a23faac2cdd6777
+ 64f2ee469fb1577675427113e478b43ab8915dfc5a3370b0b55dadd51f1415083831183748bbbd393ee54171fa12a112addea5bffd
+ 4172000e1d04402689bffffdf46cabac;
+}
+
+mars-gcm {
+ 60d7bcda163547d348b75511
+ ""
+ ""
+ ""
+ ""
+ ebf333475ccfd01e22434b02b7356886;
+ 95e77022907dd1dff7dac5c9
+ 94
+ ""
+ ""
+ ""
+ 1f643ac59e0fe29a4c1a84833c1093b9;
+ 1d26d0c6eb14ad568f86edd1
+ ""
+ dc
+ ""
+ ""
+ e8ed5ca386836f0fde3d8def53764182;
+ 9268eeee533285a6ed810c9b
+ ""
+ ""
+ 68
+ c6
+ 0a84b3ea1725580f6ff197fc09ad1d97;
+ 9daaa9060d2d4b6003062365
+ b0a54364c76c160f11896c4794846ecf
+ a14a7130c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a61
+ 36512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f50804
+ 22ebe7296754751f308114594df1ce2c029a959eb46639dda878d75cc411f58924dd49d15b515cb32c987716b9668fff
+ 9a65ff41da556c3b4ea0154dbc6a7432;
+ 6733d9ff61cdbda3b3e98787
+ 31ebfedd4705e505da1435dc
+ eaa7b1cc49ae1d50c38201a894476b3f102b75
+ 2eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97
+ 5ac307a7ba0e8c3f15b3da71b2dbe231914d92040e6099060e12312f940f512a4bea4f140ffc99e37cd4c004fe70fd9afead2070b93e171944
+ 3e3a39a40c14cf4455054df3dc812412;
+ a48030370c33d090c54215ab
+ d6b3ad54efc9a38378c5b93bf4f2aa
+ d2605faee2b03fb648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f8f28523c03d4de16
+ 00157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189
+ 0c0dc2d9d390c165b844a4fe302c9468dd61b989ec85e415c2e66a02c6a9e88e6c4b29b59526b3bba15ac8c7c773fad8cd346313d5
+ b66ce563af3c5adeb147f05f2a1332a7;
+ 196d1ebba10b0467cb9fc2712a199e533fa91563
+ ""
+ ""
+ ""
+ ""
+ a3752b6bc192c30a8b4a33090b82c8f4;
+ 08cdec3f768281e040a9b9a222bd689aef66f530
+ 6c
+ ""
+ ""
+ ""
+ 2d7f085e88e212c1d5a7470222846f6d;
+ eb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa
+ ""
+ 6a
+ ""
+ ""
+ afd0596615ac5995f94a4c4933d7bc2b;
+ 5cfb0bad7d95214ade49cb3b6f5fe8368131115c
+ ""
+ ""
+ 03
+ ac
+ 06c5e4184cedd818df6808aed1cbaca3;
+ 7ba323fe1dc8151784873f0eb5b647da6794c18b
+ 5337685a96ed65b9aca338527ef19b09
+ c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d2
+ 2bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d07983
+ 41ed7b09be9ff9174abf78851ec6b7dd1de6abae054b330e761068fcb38c10e658d4a4dcccf87c9bd972a7c3736681e7
+ 87c051ef30fb9d6b610ac3d8b367d190;
+ 91805da08da3aefc5f8584b7c5e617669c0f16e3
+ 9815d4e9cfce3ed1ecdf3d26
+ 4a7f16cb16c2e815f422cdf0c8e30308be3c31
+ e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b6d00
+ f08e36ab5ed57342834832ae777155f3b98a75495279de1d647d6cbe54143a9ccd11a1394c37aee68c4214deb21134425a11084387c60b3af4
+ 4a3532e7462571f4c0aa720877fcc127;
+ f06dc188d472a784e0c6f21195a3b9f4ae985511
+ 265febd11c164720eef9eb1c8dd0b0
+ 0951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851
+ bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff66
+ 0dea7dfec76fd70330daafa91a42de22cb7d9ccb8f762fb36eeb5cacf96cad8a5972e163c42f0ccffceab82352f7b357614c058b2f
+ 8e46584fadfee6bf54b6b3df1127e528;
+ 9c732b58db8f48af
+ ""
+ ""
+ ""
+ ""
+ 97b6cfc2d51f18dbfb036aead20cf7c9;
+ 65f7cc9e3fb90e17
+ 21
+ ""
+ ""
+ ""
+ e660c51ce4935fb6b0568b9da21fd6bc;
+ b730374ffc9bc597
+ ""
+ f5
+ ""
+ ""
+ 029a8fbbcffd6a6657ea08e6f8563c5c;
+ 6ccbb2f294b38766
+ ""
+ ""
+ fc
+ 73
+ 8a51e96b7e49dd61bf505d6be05880c1;
+ 69f6a9f2c0945ffd
+ 505003cc0cae9ce021a5f1fa4ffa9154
+ 4485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967c0a458cb948bdd40
+ 9b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd205b70
+ 51af1a674261ce3b602216b7be5490dc29b5c0fc13111ef312aee59aa415455eb45ecb08971640295ee6083d336852ff
+ 033c89302140a07d7ec18495ac6e04de;
+ e04c091d205cdad9
+ e9a79b1abf91b0851e5ca605
+ ac8451399587011677508a15dde524af3e2bee
+ 0646541a42c2ecccb44d65bad397abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a5718
+ 1322a51e98047b8ab460b5862ecb72506d86347ff23da7c246c7412e66f778c44fcac56086f6233cc65342b25825c27447162c75c4f4d47e77
+ d1c84ad7d023b7339eeb10cf9d4a54b0;
+ fd25014107c8e7d7
+ 15a92add9589d1f5c054b2d9835146
+ 05ec590294a319b9802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70d17d4569eaff59a332ba58d5
+ d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68daac90cfe22d2f1f2968cc42fa8b66
+ 7d49e4c21966171b11dcd2557bc759735b6a0f8883869a032ff7e3b7300f6c177a17c78de29b7dd1fb60dcd83df08d94b4f7b203fa
+ 9e558cfae2396ef731781539964cb64f;
+ 9ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4563d405e51881e99027b8ab9aea3cc
+ ""
+ ""
+ ""
+ ""
+ d7edfedbfaaa00b83910524a6a72a0bd;
+ f860b0009740763d96836c5f87b95460938de1288c69d80ea12ff4bb5f069b8a2e86041c
+ 1b
+ ""
+ ""
+ ""
+ 9b47dca7222907d7728d60047341be6b;
+ 9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c36800d9645563a30
+ ""
+ 8b
+ ""
+ ""
+ 4d7ff706428aed21fed40ba423e497f6;
+ a60076817523bd2abf1261b089d8f23a9c2835076a23faac2cdd67771cc667a8331f0a17
+ ""
+ ""
+ 0b
+ ed
+ 513db06c53e14e17a0a6a2358c63eb84;
+ 66283e4f834a06148f302c3973accd56f6f24e33958b8c2e2352fd61e4fa8fec816ac861
+ a8b33779f09e7a10fc02a8f48afa3080
+ ee119a52a9a817e4f2b94b0820cab383a8cffeea7c486315799dc875fba578c8ec4837898a92142b5b0677da1ac27311
+ 7b45bcfff5d5f8b6fde2893232a9f81d14517ffae475f6b94a43a67b3d380d2f9aaafe2dd721c0095c88088476892114
+ 1cabcdd7bd2c878d0d509527aba73014be8fda187aad0fa6171cdf7b40611f6e0436653ff03bdc3540fc240fbf2edf11
+ 4747f36bac04dfc0d594803a8b5f7393;
+ 50ba8095ffab1eaadf66fd22ac1976063e113ab61f813e28a1397a7974a1d7f4220c785f
+ e426a5a0e80f678d40414784
+ 2941feeffdc2eb44dc8c0d5e8f444f7f4e0c89
+ 3959b74dc23a7bb40e7e0013e5150686d2301b43a15a84e81d7f5cedaa49e2414ebf47970e560475cff206877de69146acc3ab6cf8556b7aa7
+ 83be0a213ffe127c49ec5352ec0f5542abda27387079f4e8f6e056187eb8e7afe34ef415383f54eeb5332137ca5407e3bb19019796a375286c
+ 03d0ffe3b26614eb375f0f9043d69cfa;
+ 76945948d1b8834df2196c92ec1718dcdeee0d52d9539726d2810391b3f9d10c39b07ae8
+ f08ce7cee4758a386a9943e97dedfb
+ e61e737882cd09c2b9a80f34c0fde11c2481b11fc76bfa4dbf710a9e544e0c536ca1e040f9ad5b04140d98
+ edabe08485290a4d87d13b07398a1458c2c6b61dbdbc1cccada8c1a0a9aabb6c4e3c3554f8fb1ef61614c270295dfc0ca6551ca4bd
+ 9f02629363a56a6e8067f76d0df265f5d1d4774c129186fd96e0826e4d5a6fd643b6fc7e484caa72575f7774f8d7d55529c816b3a8
+ 77d7548dfeed0ca41810c69586ef999d;
+}
+
+mars-ocb1 {
+ 60d7bcda163547d348b75511
+ 95e77022907dd1dff7dac5c9941d26d0
+ ""
+ ""
+ ""
+ 4653e79c83c9692f680b6ab67aa4cb1c;
+ c6eb14ad568f86edd1dc9268
+ eeee533285a6ed810c9b689daaa9060d
+ 2d
+ ""
+ ""
+ 9cf228b3a0a873d910ef08325178c9ce;
+ 4b6003062365b0a54364c76c
+ 160f11896c4794846ecfa14a7130c9f1
+ ""
+ 37
+ 7f
+ 3194ce1f7b3c055b5c465e9449713d73;
+ 120634c9519848a877ff77bf
+ 79192a5b50ade5d9cd739a3d1f337f29
+ ""
+ 549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c926
+ da19eb03799876ac0c7f25bbb54e051149623d839822c5305b2348306fb687a95debfb6d8463b8f61eff55879a8e4854
+ c9315ab551796c3230de8d1b783e41c6;
+ 9029df3e6057acc87638f508
+ 046733d9ff61cdbda3b3e9878731ebfe
+ dd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040e
+ f2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215
+ e6fffaeff62574ca11871e98539b5d6252724476ceaf2e6f7649e25df4c7fa2d1168bc6913bfcabbeb65cc7673d64445
+ aba7309b9f99d4d595029cb68eb9dfef;
+ abd6b3ad54efc9a38378c5b9
+ 3bf4f2aad2605faee2b03fb648e27fff
+ ""
+ 63102758fe2b69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb6
+ 41d2c5f2747177da8fb403142b15976849d6092a1f30a00a7dd86dfeae5e9a4d37a2b63ab07ee4ef461bb0c5a0ccce42767d08bf87
+ a5990263e713d60c619a4c8e15b6b3c4;
+ 5d1563259f9eb53b571ea629
+ c54d57dd2d42f70800df9fcbaca48b77
+ dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f530
+ 6ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc815178487
+ 996f3de0c448f6bcc7a05966caf6b55b9a6e89038b7b1dcf0e227940a481c7d01a8deb9ab18c66e6e40f77673084abf2237348d737
+ 12639c6038c9de5dac44e56672cb55aa;
+ 3f0eb5b647da6794c18b5337685a96ed65b9aca3
+ 38527ef19b09c063c46f88de9fd41e72
+ ""
+ ""
+ ""
+ 2a302865877be6802bf265563679f4a6;
+ d7b97e23e6eabdff3bcd211499268878dbf30f1d
+ ad89d4b9b12012e4713df46795630e79
+ 52
+ ""
+ ""
+ e504301acfb3dd72388b857ee7030835;
+ d22bb02d7100b8b649377d20a8f083455b663e4e
+ e1315f3c8f2aebfa921451dcd1af5813
+ ""
+ b7
+ ae
+ e2242b2d76d0f58177d422c14007837b;
+ 0d30ce2f1fef6ef315d0798391805da08da3aefc
+ 5f8584b7c5e617669c0f16e39815d4e9
+ ""
+ cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4
+ 289ee6d05f1e2afadef55a9be57142c9434db665577e5e471466dcf0cd8dcee27b8337966c5f1a45a88f87801fc4ec61
+ de6956f5723d140cb3147978cdaaded2;
+ cd52147ed12ca986981a874498ad0abef8bc4fcb
+ 70e27e98ef1f0446b42fb144d44b6d00
+ f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed0045633185
+ 4bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3
+ 6887543c971afe587132ed940556ec6275f8e92d4f94bcc8f31ed297ebaa6757c4353fdc1f6bdb1a870c22336f825a96
+ abce9a9e9c6f5d09e99c93d7eadfede3;
+ f9099c5ffb824173d7634c04226f30cbb7f0e4a9
+ 73a8cd190107314717a77456f3ff669c
+ ""
+ 732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1
+ f449b1339ac9985a1c4b342d1b0a5c41f15b8b2aca90c12846c792ae42057b3fd7b41111c8db756adf5a2ef5e1546e57fa0243cfb7
+ ba66681acccec14ef865b02f3c39b3f6;
+ fa4ffa91544485f1a1258b2b9b8f0911e32d65cc
+ 1770a18cbfe6effd1ff6778554acf127
+ 0485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957f4b03cf4
+ 3e89957f9a3e8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac8451399587011677508a
+ 7e1008b868fc1e9839963cd536e425796a5a83fbabd727f72bdf86fef8cf16929a5d491a4657a4228a19e366a213f820cda50268b2
+ 3f0cd60dee1bf4bedd8415232e0e5a2f;
+ 15dde524af3e2bee
+ 0646541a42c2ecccb44d65bad397abfa
+ ""
+ ""
+ ""
+ 158bc7dac7095b407e95a345ec6362d3;
+ f529ee41cf9a05c7
+ efedef3401539c51d2a90bbf7f1bfc33
+ 8a
+ ""
+ ""
+ 8bef95789b98fffc2e3a3324237b03c4;
+ b0ef5746ea8fdccc
+ d213e33f7e8a5718fd25014107c8e7d7
+ ""
+ 15
+ bd
+ a88cd72e0e1e676c5c011dcbc14d2e46;
+ a92add9589d1f5c0
+ 54b2d983514605ec590294a319b98020
+ ""
+ 68a9f891bc5ba5afabf8c3122d12d7ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e
+ 6ed48f6abe15219da489442825e579452118ad3fef19d76292398eaea3a27d2cf358a5a1dfc1810c68b5e17db646d4d3
+ b19f3b616690535f642ae58f4263880c;
+ 6b7ea2725cb2dac0
+ 7ecde95759ac46fee6dda7abc8ad68da
+ ac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4563d405e51881e99027b8ab9ae
+ a3ccf860b0009740763d96836c5f87b95460938de1288c69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186ddf1
+ f5c8dd655912fff44348c17cc0a0178fc55bbb12f4af3a017bc8db8b27c168d1feb19bcdd00b8f738adb541425412da2
+ 820fbdee601293312a0756571cdd2389;
+ f6a7a3aa7e740da9
+ 67828e3604b35b15ffaa6c36800d9645
+ ""
+ 563a308ba60076817523bd2abf1261b089d8f23a9c2835076a23faac2cdd67771cc667a8331f0a170b66283e4f834a06148f302c39
+ 201b87f6e406e13217b302fb759395dc0aa43b22b175472f45de5349ad46fd04c6fe85eb5c553432dd49fc279f668562f705ca3aa3
+ f7b7990d4d35c703d03b18b009bd6a6c;
+ 73accd56f6f24e33
+ 958b8c2e2352fd61e4fa8fec816ac861
+ a8b33779f09e7a10fc02a8f48afa3080ee119a52a9a817e4f2b94b0820cab383a8cffeea7c486315799dc8
+ 75fba578c8ec4837898a92142b5b0677da1ac273117b45bcfff5d5f8b6fde2893232a9f81d14517ffae475f6b94a43a67b3d380d2f
+ 1bc1cc2a9d971ffd42de07dfe98a00df3e83baf24c8a7b658eaaad1b61726d6b9aa527fadebb284414e9d75eadd23274710de7818f
+ 294968c6ea337be16fa4b02cdfa33e50;
+ 9aaafe2dd721c0095c8808847689211450ba8095ffab1eaadf66fd22ac1976063e113ab6
+ 1f813e28a1397a7974a1d7f4220c785f
+ ""
+ ""
+ ""
+ 91db1563a8a1d0f60253be719e1e41f1;
+ e426a5a0e80f678d404147842941feeffdc2eb44dc8c0d5e8f444f7f4e0c893959b74dc2
+ 3a7bb40e7e0013e5150686d2301b43a1
+ 5a
+ ""
+ ""
+ 83e94ddd60fb2b811905035945907c5d;
+ 84e81d7f5cedaa49e2414ebf47970e560475cff206877de69146acc3ab6cf8556b7aa776
+ 945948d1b8834df2196c92ec1718dcde
+ ""
+ ee
+ b2
+ 0d56aa6e43ad24239efcfcd726927fc1;
+ 0d52d9539726d2810391b3f9d10c39b07ae8f08ce7cee4758a386a9943e97dedfbe61e73
+ 7882cd09c2b9a80f34c0fde11c2481b1
+ ""
+ 1fc76bfa4dbf710a9e544e0c536ca1e040f9ad5b04140d98edabe08485290a4d87d13b07398a1458c2c6b61dbdbc1ccc
+ b8b85de994a54ef5dbcbd85f5eaa88e2b2464262a53859300232029741b167876b6d3195c95957d5600e31de5f275da6
+ e69278334c8133c3710564526e2016f0;
+ ada8c1a0a9aabb6c4e3c3554f8fb1ef61614c270295dfc0ca6551ca4bdb75359f91cb9d9
+ 21056b7de74fc9a9b37154ce6c0b3961
+ 79d31f06a1dd5982cbc0d7cb23841da1ae8f4ae480cda98ad6cf2bacf6f9fd3f821330c43f3df6c2b3fac7cbcf96523d
+ 4723f91801325eb8553236651c96788d73d192ee53b3f3ebd66ddd98cedbe88e245de25b1593b70f8601562d90a9b59e
+ 9e1e7295f6bb0cf520a77dc6bf4cae9411c79bf4d9e6a2a862efd982f4525bdd026b7ce5bb28b46bdf4bc4eb3e8e9675
+ d5ca1cd9e51f5441912d15626930b798;
+ d034a867642d25d54756fa5c47f16f64b837bb4926214211a1c696ba172010abb433922a
+ 22d9fd881519165eb9d85197a21cc34a
+ ""
+ c0d5ae7be8dbf98e4ffed2cf6b1372a5aa47b54fd9d70c70e117bf1cae71b3a56f0e7d839ea59cc783443d64f2ed6a29b96856beca
+ 33c0fb24bcc9948f79e7257d8816767fd83a862643e0e31b1ecde6dfc39523dbb29b396435eae70c7658cbb9442c457805713c45da
+ b0b7b3760231dd8ddd9a6378e27fadc0;
+ 34fd6544bcf86b799e2a1681160ccf055f0fd3001da597a1406d465b7b1419ea51cf858f
+ 938f6daafbd656445a09898eaa96ffc3
+ d1d2e31e4e34c94b8bfae64825ecd75a66d88eedb969ffe07669845ebb7a24c69f13d099f47166edf54538
+ e88fbf433a7ff212085179e79771f6eee7283ab178ef2b800d7b969da05780ffc1ba78c70dda7a4ca2a25e771702fb1901ecfc8a95
+ da25756b3f6d874af5fc62eb4d23153e0f42f476f6ef83622e6b704eac2b1c0ffe419780e789c457c51fddfda8c999b9a4eba0ae59
+ 8c06ff6ecbcc83696b7a3ceb00819fef;
+}
+
+mars-pmac1 {
+ 60d7bcda163547d348b75511
+ ""
+ 88349068f0361feb5ab861422204a1fb;
+ 95e77022907dd1dff7dac5c9
+ 94
+ 68e53c106eac08332168b9710686bde0;
+ 1d26d0c6eb14ad568f86edd1
+ dc9268eeee533285a6ed810c9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f1
+ e73b3d7d64f57c88e3d08c79531304db;
+ 37120634c9519848a877ff77
+ bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8f
+ 155e94d935999190f3c4707830a1627b;
+ a21f2dd88374d8cde8e160ad10997a21635c6d62
+ ""
+ 25767cba62b028dc2b28890f20b71457;
+ c9269029df3e6057acc87638f508046733d9ff61
+ cd
+ 8e847f813725a45c86f09bbdf9d3984f;
+ bda3b3e9878731ebfedd4705e505da1435dceaa7
+ b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b54
+ 0f6d60ece48580fae8d7914ab7194ccd;
+ 2cde52ebfda19d0ccc520f215eb57bb3a4f3ebbb
+ b18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e2
+ 922c357cc72223d59ef79018aa0fce6d;
+ 7fff63102758fe2b
+ ""
+ 0b46ed47aa8b8d1c15b9a1be5116955a;
+ 69ac26afa3349829
+ b9
+ 779d971e639e3f8c5e8d280d78a56a14;
+ 4586306fed54154f
+ 8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42
+ 9594bd5550eddba1050516976565ee32;
+ f70800df9fcbaca4
+ 8b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66
+ 3f3100f026a9b5c53df1ef563f2e2b96;
+ f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b
+ ""
+ a9fdd55b4c5ff6687cd49667d60d525e;
+ 6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65
+ b9
+ 09210b235e15e9984f6d728f4d266cc3;
+ aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf3
+ 0f1dad89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa92
+ 1ea465d576f919265add525cc88c6cca;
+ 1451dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e61766
+ 9c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb6
+ b4e1b487ca7856e1a27ae343a761962f;
+}
+
+mars-ocb3 {
+ 60d7bcda163547d348b75511
+ 95e77022907dd1dff7dac5c9941d
+ ""
+ ""
+ ""
+ 7c296d4449e64315d2b9f9ba0c3ff7d1;
+ 26d0c6eb14ad568f86edd1dc
+ 9268eeee533285a6ed810c9b689d
+ aa
+ ""
+ ""
+ b430fac783a66cc2daed259760916412;
+ a9060d2d4b6003062365b0a5
+ 4364c76c160f11896c4794846ecf
+ ""
+ a1
+ 67
+ 06f7540f39167c5adfddad27cf702a2c;
+ 4a7130c9f137120634c95198
+ 48a877ff77bf79192a5b50
+ ""
+ ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160
+ 871488d35db8121121e6c850c22cf29166fe1e351ce6f6027053f625dae6bded20dff82b546f8ba0806af4a9df2e3cd3
+ 1cd5f303f4b515ea7c331533b41f4ac7;
+ ad10997a21635c6d62c92690
+ 29df3e6057acc87638f5080467
+ 33d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb952953396
+ 6f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6
+ 04aecdbb5ea1f384759cb21f922d4a5e5f41759933e7e12a46761a0bb58e8b13100338f8ac4f5d71a564d51d2e7ecefc
+ 0fdac739fa9705100fb282f9c9c99668;
+ c95a97a48030370c33d090c5
+ 4215abd6b3ad54efc9a38378c5b9
+ ""
+ 3bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710
+ ecec35b67e05827d1c60b59197ddec40a4afc502e7b22194c710f2d5bb806fca221d81abdce4c507e02f65b5cca4e43f86f5f76f5f
+ 4eba3f34ab847bcb7fc65d5b06406cec;
+ ee72807a2219bfb474fd71d8
+ 91f24bb65d1563259f9eb53b571e
+ a629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cd
+ ec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f
+ ff28ac43e2c855d679ee89f7f8d4107c8a1c7c20a4f03b59544adaedd185a4e3a5a37ca45dc55e11df1cdaa7a374850225bffc3c26
+ 2da2a1575b5dc344c32a8b2a0b4c3dd8;
+ 5fe8368131115c037ba323fe1dc8151784873f0e
+ b5b647da6794c18b5337685a96ed
+ ""
+ ""
+ ""
+ f940a9debe160996da1f147aafcc566a;
+ 65b9aca338527ef19b09c063c46f88de9fd41e72
+ d7b97e23e6eabdff3bcd21149926
+ 88
+ ""
+ ""
+ 92001d0836b97d87051c1f7d9d09f202;
+ 78dbf30f1dad89d4b9b12012e4713df46795630e
+ 7952d22bb02d7100b8b649377d20
+ ""
+ a8
+ 74
+ 67e9a575f013c2692d295c6103d0d0cf;
+ f083455b663e4ee1315f3c8f2aebfa921451dcd1
+ af5813b70d30ce2f1fef6e
+ ""
+ f315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cd
+ 0a797f00e405100dadb704f4ff09a0a4a8cbe6cd46a0b27529f64b9c56f9d70e688fbe551fa24eb5d3609185b4bdceed
+ b672df8063219f6c88308bdd3a3ad799;
+ f0c8e30308be3c31e6bc58c0b7cadcb658b970e4
+ 7479a684b5aefa69a4cd52147e
+ d12ca986981a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4
+ ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc3990844
+ badad19dc5594c261a3c5f532b3dcfadfbb81fc53ed47dc2ed8327af497dd998714d1a882310f27ff3cb2c59c024d6e6
+ e4b3b99d7d2e296fb0c0de581f1b5fe9;
+ 5608fe95e81c2533e31c9c1a9851bc2810d858cb
+ bc8424d126b807e6daa089c3f909
+ ""
+ 9c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b73037
+ 21a942eb29d65d2fbf4807ccbb084336916f1003941785547a5346c7eab40931819df2d8caa2549e942e1d09b84b260c7a0dfc0a10
+ 672ef4305dcce1cfe09539670b14a261;
+ 4ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0
+ 945ffd505003cc0cae9ce021a5f1
+ fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4
+ c967c0a458cb948bdd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a3e8128f8743d16687b7bb8de
+ 2d0975faff0cd18b98e72bd93765dd3abd35cc4e3cfeb0b6cac1e15e9ed12b4aa038f51cc89b3576ff38a268be71215c4b01dcd552
+ b5237448fba31d61ebda5eeac052d5d6;
+ b9bd205b70e04c09
+ 1d205cdad9e9a79b1abf91b0851e
+ ""
+ ""
+ ""
+ 20c493b7bdf626905c987fb7bf10d8f7;
+ 5ca605ac84513995
+ 87011677508a15dde524af3e2bee
+ 06
+ ""
+ ""
+ fa2df8b2eaad48b6bdf3c9bad2938049;
+ 46541a42c2ecccb4
+ 4d65bad397abfaf529ee41cf9a05
+ ""
+ c7
+ 75
+ 435dd63a2ce8c8458535cd09b20f8d3a;
+ efedef3401539c51
+ d2a90bbf7f1bfc338ab0ef
+ ""
+ 5746ea8fdcccd213e33f7e8a5718fd25014107c8e7d715a92add9589d1f5c054b2d983514605ec590294a319b9802068
+ 64e098d90cbf96bc76262ab532cc962b17fa5c87938daba74d1af81bac2132abb0ff7c47ce79b02b4d6c863ef802d79b
+ f9732cb1c9f81e4e2a18bc027bb54a19;
+ a9f891bc5ba5afab
+ f8c3122d12d7ff3c41122d70d1
+ 7d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad
+ 68daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4563d405e51881e99027b8a
+ bd7f51b29f6c6f31d1be0eb43533bf93f1b32117242de5011d5e8b25fbb5692531fd3a6c9b48fad09bc80a142ff50ee1
+ 86ebc023b905ca6caa36f50a8e18843d;
+ b9aea3ccf860b000
+ 9740763d96836c5f87b95460938d
+ ""
+ e1288c69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c36800d964556
+ fe4fa4d02555e61c0bd04dff129a4d6936fb1f73d65dd7cd97bb33cb2367ad3cd6e837306ce8bb8f7ae139034d288069d9b25e8c60
+ ca2f4b45a793978f9bf62457f035ac75;
+ 3a308ba600768175
+ 23bd2abf1261b089d8f23a9c2835
+ 076a23faac2cdd67771cc667a8331f0a170b66283e4f834a06148f302c3973accd56f6f24e33958b8c2e23
+ 52fd61e4fa8fec816ac861a8b33779f09e7a10fc02a8f48afa3080ee119a52a9a817e4f2b94b0820cab383a8cffeea7c486315799d
+ b15d10be578b00205857262c9108b92645914a0824925535feb7486fb53037fb93d5ff7d77acede5ddf9ece2422636baa4817f4ebb
+ adff289af064bd7145e742df30acc5fd;
+ c875fba578c8ec4837898a92142b5b0677da1ac273117b45bcfff5d5f8b6fde2893232a9
+ f81d14517ffae475f6b94a43a67b
+ ""
+ ""
+ ""
+ 0742d3aab5b5f4338953a42eff9de1e4;
+ 3d380d2f9aaafe2dd721c0095c8808847689211450ba8095ffab1eaadf66fd22ac197606
+ 3e113ab61f813e28a1397a7974a1
+ d7
+ ""
+ ""
+ 9960763f7362f798c6ca3adf09317bd1;
+ f4220c785fe426a5a0e80f678d404147842941feeffdc2eb44dc8c0d5e8f444f7f4e0c89
+ 3959b74dc23a7bb40e7e0013e515
+ ""
+ 06
+ 2d
+ 1896462db7d41cf1dfc0e73f56e35e49;
+ 86d2301b43a15a84e81d7f5cedaa49e2414ebf47970e560475cff206877de69146acc3ab
+ 6cf8556b7aa776945948d1
+ ""
+ b8834df2196c92ec1718dcdeee0d52d9539726d2810391b3f9d10c39b07ae8f08ce7cee4758a386a9943e97dedfbe61e
+ 6a517fb1eddc5a9ffcf4b4dcae0c9d2e2f8f70b843e480d9b86d71fdbeebacd5a135f08de14ed70906ccbc4f6107b425
+ e699532063bc347b5273ab6c9aa5f8a7;
+ 737882cd09c2b9a80f34c0fde11c2481b11fc76bfa4dbf710a9e544e0c536ca1e040f9ad
+ 5b04140d98edabe08485290a4d
+ 87d13b07398a1458c2c6b61dbdbc1cccada8c1a0a9aabb6c4e3c3554f8fb1ef61614c270295dfc0ca6551ca4bdb75359
+ f91cb9d921056b7de74fc9a9b37154ce6c0b396179d31f06a1dd5982cbc0d7cb23841da1ae8f4ae480cda98ad6cf2bac
+ 8908a7b2b68ebc9659feb4a31163481275f0db4182b7051a9a50e9697f8115ff79368964e9661b2e2db5d2a4c86b5a23
+ 33756a80721be9f1105c7afd703e21a0;
+ f6f9fd3f821330c43f3df6c2b3fac7cbcf96523d4723f91801325eb8553236651c96788d
+ 73d192ee53b3f3ebd66ddd98cedb
+ ""
+ e88e245de25b1593b70f8601562d90a9b59ed034a867642d25d54756fa5c47f16f64b837bb4926214211a1c696ba172010abb43392
+ cdcec7225d6eb19a12720cc24c2a672559618debfdf0ee0d0b350e2701a69124f28d1b76b322cecdadbc67e99342c59dabd11fbf23
+ fb30f854d45a706e84616a756a52e711;
+ 2a22d9fd881519165eb9d85197a21cc34ac0d5ae7be8dbf98e4ffed2cf6b1372a5aa47b5
+ 4fd9d70c70e117bf1cae71b3a56f
+ 0e7d839ea59cc783443d64f2ed6a29b96856beca34fd6544bcf86b799e2a1681160ccf055f0fd3001da597
+ a1406d465b7b1419ea51cf858f938f6daafbd656445a09898eaa96ffc3d1d2e31e4e34c94b8bfae64825ecd75a66d88eedb969ffe0
+ 98463b6aa0363435ef5f9a71e67406202f51153781195a36bf467b301bf4a676c5af0b7011e15f1ecff79112847529137666ffe910
+ 684543c8dbf9b01aee18f5eba0153a24;
+}
+
+mars-ocb3-mct {
+ 56 3ba8a3d94c3f67e9cef8cf2142b367f7;
+ 52 f743099826d0e38c48faf27d3edd5b22;
+ 48 4345a17ed61d2a7b9289f0e12e4350f5;
+ 44 ef3ad940f5e754a02317f3f1c489028c;
+ 40 c618d5f97d8913f90a91caed561346c7;
+ 36 96249ddf7bd91b1df2e2aed3c09bd194;
+ 32 1f789304aff2376bf2feba8aa9191a05;
+ 28 7a339727e025fcf65c08152217b95583;
+ 24 d4d38f1f399005a03a185887fbcc6737;
+ 20 45e7020dbfdd5f6d31cb441096faf69c;
+ 16 6b5c2f90abb45cda3622baa74d486f02;
+ 56 15a0597529ff0ec495e2abc1;
+ 52 fbd7bfc60b66a65582e96109;
+ 48 ae651ff80d12c1940539ae3e;
+ 44 35db8939f38ed596f9940968;
+ 40 fc4127740b0b0b7c07d2cf62;
+ 36 282eec1a27cf55e9cda791b1;
+ 32 95f745dd397a29d2dbcca030;
+ 28 6935deaa6bc7da04dc7ab3e9;
+ 24 f46ff7af02ea94fa45404e09;
+ 20 2f41619c9f36bc9ed459d3b9;
+ 16 c02f5b63d1ccbe71e928b16f;
+ 56 05f4e466ef576d08;
+ 52 b260ce024131b9ba;
+ 48 ad7f2b73670c5238;
+ 44 00a12cf14f6300bb;
+ 40 f0bfc04f2ea1275a;
+ 36 48585bf1735225ea;
+ 32 838abfef38920bee;
+ 28 fe4f81e7b258e614;
+ 24 b1791137318f5946;
+ 20 d67d45622c856251;
+ 16 f34b97c87f3e6823;
+}
ba6933819299c71699a99f08f678178b
52f88a7b283c1f7bdf7b6faa5011c7d8 5096f2bfc82ae6e2d9495515c277fa70;
}
+
+noekeon-cmac {
+ e4bef260d7bcda163547d348b7551195
+ ""
+ 2863ef2fdd68856576cdd771bfa6f2d5;
+ e77022907dd1dff7dac5c9941d26d0c6
+ eb
+ f8e7683bb1eaa6647a054678315b5eda;
+ 14ad568f86edd1dc9268eeee533285a6
+ ed810c9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a8
+ 0a792a2d00ebcf99531795f4b5014e2e;
+ 77ff77bf79192a5b50ade5d9cd739a3d
+ 1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10
+ c123e79e5caf935e4534444d32d814d3;
+}
+
+noekeon-ccm {
+ e4bef260d7bcda163547d348b7551195
+ e77022907dd1dff7dac5c9
+ ""
+ ""
+ ""
+ 49ba308e;
+ 941d26d0c6eb14ad568f86edd1dc9268
+ eeee533285a6ed810c9b68
+ 9d
+ ""
+ ""
+ bf7a3a76;
+ aaa9060d2d4b6003062365b0a54364c7
+ 6c160f11896c4794846ecf
+ ""
+ a1
+ 07
+ f4749361;
+ 4a7130c9f137120634c9519848a877ff
+ 77bf79192a5b50ade5
+ d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10
+ 997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7
+ 4c78845e20c686f9ff85982d36d3e9aa511ca2e24d03978efbcc2728d499114cfec92bac5f9913c6fab485e7dced9599
+ ed048b86e5dbb933f5893750dc0634cd;
+ b1cc49ae1d50c38201a894476b3f102b
+ 752eb9529533966f27
+ 043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbb
+ b18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac
+ 0c825df862df85bf1bb99434c39ce83a392f0e03ca915677bfc6f7de8cf1643c70f679f8dc8d245fb2c84be5f05b5e6064ff017589
+ c9d921b8c460e2dab218d13a0609a344;
+}
+
+noekeon-eax {
+ e4bef260d7bcda163547d348b7551195
+ ""
+ ""
+ ""
+ ""
+ 086d221cf45f48c8c1f0c176c227db42;
+ e77022907dd1dff7dac5c9941d26d0c6
+ eb
+ ""
+ ""
+ ""
+ 5599da97576ed0f456791a6d00e17288;
+ 14ad568f86edd1dc9268eeee533285a6
+ ""
+ ed
+ ""
+ ""
+ 40e6658bc9910a80906ad1337c633782;
+ 810c9b689daaa9060d2d4b6003062365
+ ""
+ ""
+ b0
+ f2
+ 205c5f8a0dbeefddbead7141069de5d7;
+ a54364c76c160f11896c4794846ecfa1
+ 4a7130c9f137120634c9519848a877ff
+ 77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd8
+ 8374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd47
+ 3aae83e95da014773b3575f62054485064a2e2070a0449ab21a5dcdda2ff10d572e475a29d0bb4710a95c109641de055
+ 8dc62b8af3aeb306e9469d238906612e;
+ 05e505da1435dceaa7b1cc49ae1d50c3
+ 8201a894476b3f102b752eb9529533
+ 966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4
+ f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe
+ 5fe35fcbf55279bdca2295b483181ccff932771ccd59aa3e35b39b6564032af118547a9704fffe57c789a88b70c7eca6eaabea82b8
+ 4953808f5678ba307676326facca87d2;
+}
+
+noekeon-gcm {
+ e4bef260d7bcda163547d348b7551195
+ ""
+ ""
+ ""
+ ""
+ d739a8af18e930e49547f57c7454eb47;
+ e77022907dd1dff7dac5c9941d26d0c6
+ eb
+ ""
+ ""
+ ""
+ 6b26f591dfb442623c1590caefa4d323;
+ 14ad568f86edd1dc9268eeee533285a6
+ ""
+ ed
+ ""
+ ""
+ 77fc8f1632e4f4294f6b9df680afc350;
+ 810c9b689daaa9060d2d4b6003062365
+ ""
+ ""
+ b0
+ 26
+ e6aa7e364110e5c886e865b8fbffbece;
+ a54364c76c160f11896c4794846ecfa1
+ 4a7130c9f137120634c9519848a877ff
+ 77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd8
+ 8374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd47
+ 7d5aef8b63a47da6a441fa4e9b36c31c39c58ac1d95728acf41ca1f81784cfb58b66ad385bc75e43062531cb3e5a5662
+ 8dcf9c1d3abaf968a359afb853e866bc;
+ 05e505da1435dceaa7b1cc49ae1d50c3
+ 8201a894476b3f102b752eb9
+ 529533966f27043eb621b7f65b000961040ef2
+ f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378
+ 55ada77e6525df0ec6c424d43cedc25f04a9b1d37d2813c1ebc6a35d157c3137cb5f04753e86676a111d72e7303bb8430ac48f65fa5b125e7a
+ 8c0d31d253b49759c1289ca15bdd068a;
+ c5b93bf4f2aad2605faee2b03fb648e2
+ 7fff63102758fe2b69ac26afa33498
+ 29b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563
+ 259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f76
+ 3e98ad97b1901fa089ddb06696ad688a3de2274b81d49c3198c17b2c1bd19556d0679d64d61f034880c89f111631bf78c4512599d7
+ 5942a749a90e4af467a8a5782590dc69;
+}
+
+noekeon-ocb1 {
+ e4bef260d7bcda163547d348b7551195
+ e77022907dd1dff7dac5c9941d26d0c6
+ ""
+ ""
+ ""
+ 5081208cd2d5472d061211afba47e43a;
+ eb14ad568f86edd1dc9268eeee533285
+ a6ed810c9b689daaa9060d2d4b600306
+ 23
+ ""
+ ""
+ e7162034dc92f809d9d9e7e41d9018bc;
+ 65b0a54364c76c160f11896c4794846e
+ cfa14a7130c9f137120634c9519848a8
+ ""
+ 77
+ 59
+ fb7d568a9d2b0d8d33ca41930bd73d3f;
+ ff77bf79192a5b50ade5d9cd739a3d1f
+ 337f29549e6b0d27a4ba234085406a61
+ ""
+ 36512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f50804
+ 86ec994914704bd64a4a2b519d43c2efd4554cd0e7cc41a91f25137ac94218e5622df9670340515ef947f90cfe6c0484
+ e72bacd856c8262a0d0bfc10ffb9fdd4;
+ 6733d9ff61cdbda3b3e9878731ebfedd
+ 4705e505da1435dceaa7b1cc49ae1d50
+ c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda1
+ 9d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2
+ 83eac3304197940d9942306411887d6809d9f04a4bdcea111a877f2579779bbb9dcc0738ea8e05cfd3aa48823ca8abd8
+ 76d9c5343a98b1a9e90c8ce4978efd2b;
+ 605faee2b03fb648e27fff63102758fe
+ 2b69ac26afa3349829b94586306fed54
+ ""
+ 154f8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800
+ 18adeeddc2d0656141002e939240aa51080969442d958a78b499fb587f585c6688fed54c528603e75c756c490fa9f1486775a01514
+ 1974d395a27da8b706de45c0821c6e68;
+ df9fcbaca48b77dba189196d1ebba10b
+ 0467cb9fc2712a199e533fa9156308cd
+ ec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0b
+ ad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b
+ 8c38ca85e4711e354e2662ff977da8ed51aca92d50c1fc40e21fde2e481f93e5c9fc454881eea55c8b6758ce6bf6adff18e01825af
+ cbe1c75a2354cf5dc1df8a6eb6ede687;
+}
+
+noekeon-pmac1 {
+ e4bef260d7bcda163547d348b7551195
+ ""
+ 12679e29381d4258973a3d59f3405ec9;
+ e77022907dd1dff7dac5c9941d26d0c6
+ eb
+ a8cf4e78783c841939afff131c3b0b42;
+ 14ad568f86edd1dc9268eeee533285a6
+ ed810c9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a8
+ 1b01bbe2a8cbae52485e4d410f94ce1e;
+ 77ff77bf79192a5b50ade5d9cd739a3d
+ 1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10
+ 35b9675a79680b83422e4282cc260583;
+}
+
+noekeon-ocb3 {
+ e4bef260d7bcda163547d348b7551195
+ e77022907dd1dff7dac5c9941d26
+ ""
+ ""
+ ""
+ 064d07192f9b79d8bc4611a94783465b;
+ d0c6eb14ad568f86edd1dc9268eeee53
+ 3285a6ed810c9b689daaa9060d2d
+ 4b
+ ""
+ ""
+ 37ad7dbe61111839a2bbead7eec6358a;
+ 6003062365b0a54364c76c160f11896c
+ 4794846ecfa14a7130c9f1371206
+ ""
+ 34
+ 76
+ 73f39959389362724e3785d929b00e8c;
+ c9519848a877ff77bf79192a5b50ade5
+ d9cd739a3d1f337f29549e
+ ""
+ 6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029
+ 820db0cbad206848e689523feda637ed12f58eaa9f133457937c505778b55369994f1c339ca3d2c044578450d5905c22
+ a0205c94e65a8712262a1d127f9d22da;
+ df3e6057acc87638f508046733d9ff61
+ cdbda3b3e9878731ebfedd4705
+ e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2
+ fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3
+ d79866f055cda0abb2ad06098f8c651ed32d5550d021bfd59fffd34433b04483d0d402fce3309a760720fadd094c8ee1
+ 14c60ff87068d3d52be11c8472174f77;
+ ad54efc9a38378c5b93bf4f2aad2605f
+ aee2b03fb648e27fff63102758fe
+ ""
+ 2b69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f
+ dcda3a90b5db824f1d54c569db8d543bb323ff0aa596a8779b7b94c3f397b193e3762cea731fe84ed5e7bd517641466550043faad9
+ b92101660872e1e7a951e8d8bab834c9;
+ 9eb53b571ea629c54d57dd2d42f70800
+ df9fcbaca48b77dba189196d1ebb
+ a10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b
+ 0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da67
+ 42b20072cef90e896f11993737b645f8e42c172527cd4ddaa5ec2e54d4bb7f234062d707b63c87624b8e16273bce20e835f3374199
+ 915583e7c80edec73b6d59c12a2a196f;
+}
+
+noekeon-ocb3-mct {
+ 16 4d9b245d6fab392f1c5364a2ef5b96fb;
+ 16 3b08aa07a8a40dc29e87a831;
+ 16 9e400fc6449969f2;
+}
88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e 129
0000000000000000 5b78d3a43dfff1f1;
}
+
+rc2-cmac {
+ 60d7bcda163547d348b7551195e77022907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268ee
+ ""
+ 994f0987c07cbba3;
+ ee533285a6ed810c9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a71
+ 30
+ 93e320d01033928d;
+ c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085
+ 406a6136512061f7080cc07df0591d8fa21f2dd88374d8cd
+ ba4c9972985a3777;
+ e8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731eb
+ fedd4705e505da1435dceaa7b1cc49ae1d50c3
+ fb945bb5060a692c;
+ 8201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26afa33498
+ ""
+ 33d92d711438bf90;
+ 29b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a
+ 22
+ d387a2b3add24161;
+ 260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22b
+ b02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2a
+ 200579382f8fefd7;
+ ebfa921451dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a874498ad0abef8bc4fcb70e27e98
+ ef1f0446b42fb144d44b6d00f06dc188d472a7
+ 72b14ddabaa01c99;
+ 84e0c6f21195a3b9f4ae985511265febd11c16
+ ""
+ 35d8b20b8aedd4c5;
+ 4720eef9eb1c8dd0b00951f284649016ed0045
+ 63
+ 3c8051aab08b5e2a;
+ 31854bc78bf43966eb0cfa9138ddc399084456
+ 08fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126
+ d71ceb7b023f4a2a;
+ b807e6daa089c3f9099c5ffb824173d7634c04
+ 226f30cbb7f0e4a973a8cd190107314717a774
+ 7cb1fd4850d2b1cb;
+ 56f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9b
+ ""
+ 8db7f9520ec921d2;
+ c597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0cae9c
+ e0
+ 53c35ba18d421787;
+ 21a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18c
+ bfe6effd1ff6778554acf1270485b203a3c1c4c967c0a458
+ d6409d3b48a62658;
+ cb948bdd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957
+ f4b03cf43e89957f9a3e8128f8743d16687b7b
+ 9ffecd00a5ce33b6;
+}
+
+rc2-ccm {
+ 60d7bcda163547d348b7551195e77022907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268ee
+ ee5332
+ ""
+ ""
+ ""
+ 0e756e3d;
+ 85a6ed810c9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f1
+ 371206
+ 34
+ ""
+ ""
+ 88075561;
+ c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a61365120
+ 61f708
+ ""
+ 0c
+ e4
+ 677a1fdd;
+ c07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f50804
+ 6733d9ff61
+ cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49
+ ae1d50c38201a894476b3f102b752eb9529533966f27043e
+ aa2e353749ab572e5ea55be5be368bae0ca3cd5604ec9c06
+ bbdce19a0df3c05b;
+ b621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbb
+ b18ac6c95a
+ 97a48030370c33d090c54215abd6b3ad54efc9
+ a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac
+ a1b2416f66d57ca9034827ff55b17cfac62108e8a10a62c3aec1de6d6a
+ af60612dfed6edb3;
+ 26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c
+ 6b08ac
+ ""
+ ""
+ ""
+ ef7e40ab;
+ 8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e79
+ 52d22b
+ b0
+ ""
+ ""
+ 9cef3d08;
+ 2d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd
+ 52147e
+ ""
+ d1
+ a9
+ 0e3165e9;
+ 2ca986981a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d1
+ 26b807e6da
+ a089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973
+ a8cd190107314717a77456f3ff669c732b58db8f48af65f7
+ 79a7ec7b8d3aad1c29ce22222d9089766c6892e25284af53
+ 1a749a4b280e03eb;
+ cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957
+ f4b03cf43e
+ 89957f9a3e8128f8743d16687b7bb8deb9bd20
+ 5b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac845139958701
+ c1255583506986b100df1504190df39ec531be3506347bc3db4ab4ec82
+ 993490ca3359ed04;
+ 1677508a15dde524af3e2bee0646541a42c2ec
+ ccb44d
+ ""
+ ""
+ ""
+ 2848a767;
+ 65bad397abfaf529ee41cf9a05c7efedef3401
+ 539c51
+ d2
+ ""
+ ""
+ e0651099;
+ a90bbf7f1bfc338ab0ef5746ea8fdcccd213e3
+ 3f7e8a
+ ""
+ 57
+ a9
+ 9135e83e;
+ 18fd25014107c8e7d715a92add9589d1f5c054
+ b2d9835146
+ 05ec590294a319b9802068a9f891bc5ba5afabf8c3122d12
+ d7ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe07
+ a0219d75977a704b34340dae9a6f96be4baaa1ad3ee96afa
+ b1e6a4f9015ad908;
+ 9753ee1a957eb6d6699e6b7ea2725cb2dac07e
+ cde95759ac
+ 46fee6dda7abc8ad68daac90cfe22d2f1f2968
+ cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4563d40
+ 612f7d0ab987bbd987e78707fa59388a40cd95b609e3b0df2298712134
+ 242d9a4c7c587d14;
+ 5e51881e99027b8ab9aea3ccf860b0009740763d96836c5f87b954
+ 60938d
+ ""
+ ""
+ ""
+ 9ebdeb8f;
+ e1288c69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186dd
+ f1f6a7
+ a3
+ ""
+ ""
+ c53713f3;
+ aa7e740da967828e3604b35b15ffaa6c36800d9645563a308ba600
+ 768175
+ ""
+ 23
+ ca
+ 704b73f9;
+ bd2abf1261b089d8f23a9c2835076a23faac2cdd67771cc667a833
+ 1f0a170b66
+ 283e4f834a06148f302c3973accd56f6f24e33958b8c2e23
+ 52fd61e4fa8fec816ac861a8b33779f09e7a10fc02a8f48a
+ 49e3c85b0d02dd9f89914d75405cfac2f343deccb9d98391
+ 95c00f9b22962366;
+ fa3080ee119a52a9a817e4f2b94b0820cab383a8cffeea7c486315
+ 799dc875fb
+ a578c8ec4837898a92142b5b0677da1ac27311
+ 7b45bcfff5d5f8b6fde2893232a9f81d14517ffae475f6b94a43a67b3d
+ 8eccebfa67d50519fadda30deee9c4d16575a61eb68adf6157271bdabd
+ 1dbaccd5b26fc6e2;
+}
+
+rc2-eax {
+ 60d7bcda163547d348b7551195e77022907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268ee
+ ""
+ ""
+ ""
+ ""
+ 493b1fd04ede5d08;
+ ee533285a6ed810c9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a71
+ 30
+ ""
+ ""
+ ""
+ 21a99e853cf8d624;
+ c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085
+ ""
+ 40
+ ""
+ ""
+ c2a4952faeb51fe5;
+ 6a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e
+ ""
+ ""
+ 60
+ d2
+ bf5432b8192d764c;
+ 57acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c3
+ 8201a894476b3f10
+ 2b752eb9529533966f27043eb621b7f65b000961040ef2f9
+ b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57b
+ f9c3cc1576f674b14e65fbe890be777d513381d3fbfaf3b6
+ 3b7bbf2f56718d0b;
+ b3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605f
+ aee2b03fb648e2
+ 7fff63102758fe2b69ac26afa3349829b94586
+ 306fed54154f8f28523c03d4de1600157846b710ee72807a2219bfb474
+ 8d354144a9ae2bfb22f92a7c7bc3655d62b2b56d972a0b48fdc527118a
+ 168314d144ee4c2f;
+ fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe836813111
+ ""
+ ""
+ ""
+ ""
+ 8e3a0ea494b5dd15;
+ 5c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af
+ 58
+ ""
+ ""
+ ""
+ 3bb40705efd17087;
+ 13b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d4
+ ""
+ 4b
+ ""
+ ""
+ 02dc7bc996b3d08a;
+ 6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973
+ ""
+ ""
+ a8
+ 46
+ 593604619e5f140b;
+ cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967c0a458cb948bdd
+ 409b687fa3a6827b
+ 480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a
+ 3e8128f8743d16687b7bb8deb9bd205b70e04c091d205cda
+ b775f9f9970f69be179df624ffa0a971fd60e1a77897730b
+ 1f3bee3056b77bef;
+ d9e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a5718fd25014107c8e7d715a92add9589d1f5c054b2d983514605ec590294a319
+ b9802068a9f891
+ bc5ba5afabf8c3122d12d7ff3c41122d70d17d
+ 4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea272
+ e4ad70206a32030a723a97c5fa7c051f0e47e4c419567c9f2465e6082b
+ b4e14cf29446000e;
+ 5cb2dac07ecde95759ac46fee6dda7abc8ad68
+ ""
+ ""
+ ""
+ ""
+ e48136f1558ef9d4;
+ daac90cfe22d2f1f2968cc42fa8b669ed3bb35
+ 42
+ ""
+ ""
+ ""
+ 75a875a6cf6822dc;
+ a9cf44bbc8c6254d980398bd94e66eb4563d40
+ ""
+ 5e
+ ""
+ ""
+ aff6510c3cfc9cf8;
+ 51881e99027b8ab9aea3ccf860b0009740763d
+ ""
+ ""
+ 96
+ 73
+ 0fbcddfb90453138;
+ 836c5f87b95460938de1288c69d80ea12ff4bb
+ 5f069b8a2e86041c
+ 1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b3
+ 5b15ffaa6c36800d9645563a308ba60076817523bd2abf12
+ 8c0f4a82cdc742cf10c6bcd81f08fe54d44602b6b04d84cb
+ 6048b808054d2c5f;
+ 61b089d8f23a9c2835076a23faac2cdd67771c
+ c667a8331f0a17
+ 0b66283e4f834a06148f302c3973accd56f6f2
+ 4e33958b8c2e2352fd61e4fa8fec816ac861a8b33779f09e7a10fc02a8
+ b136f77a805e9042723b12db98a1ab0c8af27b687ea3b81bd09cf15d20
+ 94b18788b3964b32;
+ f48afa3080ee119a52a9a817e4f2b94b0820cab383a8cffeea7c48
+ ""
+ ""
+ ""
+ ""
+ 441faa27cc4c5c56;
+ 6315799dc875fba578c8ec4837898a92142b5b0677da1ac273117b
+ 45
+ ""
+ ""
+ ""
+ eae3c4243cea46f9;
+ bcfff5d5f8b6fde2893232a9f81d14517ffae475f6b94a43a67b3d
+ ""
+ 38
+ ""
+ ""
+ 9a3430a79df38876;
+ 0d2f9aaafe2dd721c0095c8808847689211450ba8095ffab1eaadf
+ ""
+ ""
+ 66
+ 2c
+ 0cb5f535e70f4099;
+ fd22ac1976063e113ab61f813e28a1397a7974a1d7f4220c785fe4
+ 26a5a0e80f678d40
+ 4147842941feeffdc2eb44dc8c0d5e8f444f7f4e0c893959
+ b74dc23a7bb40e7e0013e5150686d2301b43a15a84e81d7f
+ 6a855a701998a62f385b9ec42102a67ef354925d18569dd8
+ eac5dfe4f5cbfff8;
+ 5cedaa49e2414ebf47970e560475cff206877de69146acc3ab6cf8
+ 556b7aa7769459
+ 48d1b8834df2196c92ec1718dcdeee0d52d953
+ 9726d2810391b3f9d10c39b07ae8f08ce7cee4758a386a9943e97dedfb
+ 9cf8b628ab6c3e8c69c289c3564027ff0de5e6bcecc38c05b8d1b7ec0a
+ fd274b8e3c469eb6;
+}
+
+rc2-gcm {
+ 60d7bcda163547d348b7551195e77022907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268ee
+ ""
+ ""
+ ""
+ ""
+ 359ae96bacf96c86;
+ ee533285a6ed810c9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a71
+ 30
+ ""
+ ""
+ ""
+ b106f982ce0fa16f;
+ c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085
+ ""
+ 40
+ ""
+ ""
+ 83c2efaff3e6fdf8;
+ 6a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e
+ ""
+ ""
+ 60
+ c9
+ dcac5bc0a6fc80b2;
+ 57acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c3
+ 8201a894476b3f10
+ 2b752eb9529533966f27043eb621b7f65b000961040ef2f9
+ b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57b
+ 9c8dd0c92811769d381b46a75e60b5d80aebe054d178080f
+ bae3d5a852937cf2;
+ b3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605f
+ aee2b03f
+ b648e27fff63102758fe2b
+ 69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72
+ 24efd192d24c0a27bb0453a186632e8084dee9028fd647362aa26cf46ed118f682
+ 1505f15227faa14f;
+ 807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b
+ 77dba189196d1e
+ bba10b0467cb9fc2712a199e533fa9156308cd
+ ec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c
+ fe9f005b0bbe7851e82e3e55aadc6fa3297c4dc6aac7da88eea83d77c1
+ ca6d92a0f8474851;
+ 571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d
+ ""
+ ""
+ ""
+ ""
+ 644405a0cd8f478c;
+ 7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52
+ 14
+ ""
+ ""
+ ""
+ 986911f8fb61ffd2;
+ 7ed12ca986981a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc84
+ ""
+ 24
+ ""
+ ""
+ 55348e0c9fadf225;
+ d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc17
+ ""
+ ""
+ 70
+ 63
+ 399484cb038779bb;
+ a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee06
+ 46541a42c2ecccb4
+ 4d65bad397abfaf529ee41cf9a05c7efedef3401539c51d2
+ a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a5718
+ c734efcfe1131a326af5fd518ab1033e7ffd7c4eb825b4c1
+ 8255ef3dc1ff72a3;
+ fd25014107c8e7d715a92add9589d1f5c054b2d983514605ec590294a319b9802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68daac90cfe22d2f1f2968cc42fa8b66
+ 9ed3bb35
+ 42a9cf44bbc8c6254d9803
+ 98bd94e66eb4563d405e51881e99027b8ab9aea3ccf860b0009740763d96836c5f
+ 7b2425dc58e780f0ab6b356cdb6ad2223d2dd69372109f08203100aa9095ec1551
+ 094f16bdf157a900;
+ 87b95460938de1288c69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c36800d9645563a308ba60076817523bd2abf1261b089d8f23a9c2835076a23faac2cdd67771cc667a8331f0a170b66283e4f834a06148f302c3973accd56f6f24e33
+ 958b8c2e2352fd
+ 61e4fa8fec816ac861a8b33779f09e7a10fc02
+ a8f48afa3080ee119a52a9a817e4f2b94b0820cab383a8cffeea7c4863
+ 1118c134e5ab39c5332fba8f3e0a566361c72bc4fd4a14219400ac57e7
+ b8a684bad429d427;
+ 15799dc875fba578c8ec4837898a92142b5b06
+ ""
+ ""
+ ""
+ ""
+ 441a5fc1a7aa3965;
+ 77da1ac273117b45bcfff5d5f8b6fde2893232
+ a9
+ ""
+ ""
+ ""
+ c2d97eafb2d4dec5;
+ f81d14517ffae475f6b94a43a67b3d380d2f9a
+ ""
+ aa
+ ""
+ ""
+ 137e2f9a5fbfaed9;
+ fe2dd721c0095c8808847689211450ba8095ff
+ ""
+ ""
+ ab
+ 8e
+ 1499fe34d82b9009;
+ 1eaadf66fd22ac1976063e113ab61f813e28a1
+ 397a7974a1d7f422
+ 0c785fe426a5a0e80f678d404147842941feeffdc2eb44dc
+ 8c0d5e8f444f7f4e0c893959b74dc23a7bb40e7e0013e515
+ 46c4eff1fd15b9be037e2e240b8845cc9e7e2530ae6214ea
+ 9feaa7393f439893;
+ 0686d2301b43a15a84e81d7f5cedaa49e2414e
+ bf47970e
+ 560475cff206877de69146
+ acc3ab6cf8556b7aa776945948d1b8834df2196c92ec1718dcdeee0d52d9539726
+ 7af0b728198469b00a3792e3640858ea8e10f4f9a0ee2f97b007f3961499d92d0d
+ 1d5b27a15b866945;
+ d2810391b3f9d10c39b07ae8f08ce7cee4758a
+ 386a9943e97ded
+ fbe61e737882cd09c2b9a80f34c0fde11c2481
+ b11fc76bfa4dbf710a9e544e0c536ca1e040f9ad5b04140d98edabe084
+ dab65bbaad4fa9e2aeee14886c89799acfd26a90de80cd6851f05113d3
+ c547859e516e9528;
+ 85290a4d87d13b07398a1458c2c6b61dbdbc1cccada8c1a0a9aabb
+ ""
+ ""
+ ""
+ ""
+ 666def937cca91b5;
+ 6c4e3c3554f8fb1ef61614c270295dfc0ca6551ca4bdb75359f91c
+ b9
+ ""
+ ""
+ ""
+ cb3f188911d99a1a;
+ d921056b7de74fc9a9b37154ce6c0b396179d31f06a1dd5982cbc0
+ ""
+ d7
+ ""
+ ""
+ 223747afb3570769;
+ cb23841da1ae8f4ae480cda98ad6cf2bacf6f9fd3f821330c43f3d
+ ""
+ ""
+ f6
+ f4
+ 6ae1ee13e1831acb;
+ c2b3fac7cbcf96523d4723f91801325eb8553236651c96788d73d1
+ 92ee53b3f3ebd66d
+ dd98cedbe88e245de25b1593b70f8601562d90a9b59ed034
+ a867642d25d54756fa5c47f16f64b837bb4926214211a1c6
+ d995a4197fa15265ee44b445bc0d3940c486f9c34ba9077e
+ 0b047045426e23e6;
+ 96ba172010abb433922a22d9fd881519165eb9d85197a21cc34ac0
+ d5ae7be8
+ dbf98e4ffed2cf6b1372a5
+ aa47b54fd9d70c70e117bf1cae71b3a56f0e7d839ea59cc783443d64f2ed6a29b9
+ a4ed2fa0d3f42b2c3270ac0801aeaa7f28f57b101c8a9a1c0e45a046e9c6887b00
+ 4c3c11a4709bcf9c;
+ 6856beca34fd6544bcf86b799e2a1681160ccf055f0fd3001da597
+ a1406d465b7b14
+ 19ea51cf858f938f6daafbd656445a09898eaa
+ 96ffc3d1d2e31e4e34c94b8bfae64825ecd75a66d88eedb969ffe07669
+ a1a0fe6856d107a0b49d164b72c0102a06bfc6ea17723f7587fab4808c
+ d797a4abd2ac973e;
+}
+
+rc2-ocb1 {
+ 60d7bcda163547d348b7551195e77022907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268ee
+ ee533285a6ed810c
+ ""
+ ""
+ ""
+ 1a9b5d9930de70b3;
+ 9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9
+ 519848a877ff77bf
+ 79
+ ""
+ ""
+ c8a18423542f2476;
+ 192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8f
+ a21f2dd88374d8cd
+ ""
+ e8
+ 65
+ 1ad7745b69b0db1f;
+ e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfe
+ dd4705e505da1435
+ ""
+ dceaa7b1cc49ae1d50c38201a894476b3f102b752eb95295
+ 702a8f6236f63b37d12754e285b48acd278a5dd319781c47
+ 4aed0840ec1cbc36;
+ 33966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb5
+ 7bb3a4f3ebbbb18a
+ c6c95a97a48030370c33d090c54215abd6b3ad54efc9a383
+ 78c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe
+ 63872e8fa08cbc02a9b67199cf4f8e805df8021d7dc7b857
+ 7dc44cfa7b6a75c1;
+ 2b69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219bfb474
+ fd71d891f24bb65d
+ ""
+ 1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba1
+ 0e8b2f665c8e05920b18889a94a59262da8d5511e504ff00740151570d
+ aa8fbbd1631944b9;
+ 89196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f530
+ 6ceb0c6b08ac8b0a
+ 22260c571b4a42bb8fdb233bfa6a5cfb0bad7d
+ 95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5
+ fa9b97df764582e8b06700b70f488912e52bb40512b7e82546c98beea3
+ 6125dbe65becfe77;
+ b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d07983
+ 91805da08da3aefc
+ ""
+ ""
+ ""
+ 201550d036fd21c4;
+ 5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae9855
+ 11265febd11c1647
+ 20
+ ""
+ ""
+ 980aada67611e269;
+ eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3fb90e17
+ 21b730374ffc9bc5
+ ""
+ 97
+ a0
+ 772be2781de4d5f1;
+ f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a3e8128f8743d
+ 16687b7bb8deb9bd
+ ""
+ 205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac
+ 935c1246b3c54e88b1612b1ae91add5d006c1da2eee504bf
+ cb750259096356be;
+ 8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a5718fd25014107c8e7d715a92add9589d1f5c054b2d983514605ec590294a319b9802068a9f891bc5ba5afabf8c3
+ 122d12d7ff3c4112
+ 2d70d17d4569eaff59a332ba58d5d5589bfe079753ee1a95
+ 7eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7
+ e934e27dfd22901f7dee3fbdbd8380d67e381b1b0a969ef5
+ 00818ef2133898d7;
+ abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4563d405e51881e99027b8ab9aea3ccf860b0009740763d96836c5f87b95460938de1288c69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa
+ 6c36800d9645563a
+ ""
+ 308ba60076817523bd2abf1261b089d8f23a9c2835076a23faac2cdd67
+ 2d45ecd08b4263bcdcde76394694aadf336f30ba6b70a6109cc0c01041
+ e1d92d792d66bbd0;
+ 771cc667a8331f0a170b66283e4f834a06148f302c3973accd56f6f24e33958b8c2e2352fd61e4fa8fec816ac861a8b33779f09e7a10fc02a8f48afa3080ee119a52a9a817e4f2b94b0820cab383a8cffeea7c486315799dc875fba578c8ec4837898a92142b5b0677da1ac273117b45bcfff5d5f8b6fd
+ e2893232a9f81d14
+ 517ffae475f6b94a43a67b3d380d2f9aaafe2d
+ d721c0095c8808847689211450ba8095ffab1eaadf66fd22ac1976063e
+ 801610881c1b88c3db1db411c93abbac039ff78a579e99226ebecc9b95
+ 21d1073d1325dd61;
+ 113ab61f813e28a1397a7974a1d7f4220c785f
+ e426a5a0e80f678d
+ ""
+ ""
+ ""
+ 4366d16a510e7a2d;
+ 404147842941feeffdc2eb44dc8c0d5e8f444f
+ 7f4e0c893959b74d
+ c2
+ ""
+ ""
+ 71128105ccb95e0c;
+ 3a7bb40e7e0013e5150686d2301b43a15a84e8
+ 1d7f5cedaa49e241
+ ""
+ 4e
+ 7b
+ 2f6c2965368d5936;
+ bf47970e560475cff206877de69146acc3ab6c
+ f8556b7aa7769459
+ ""
+ 48d1b8834df2196c92ec1718dcdeee0d52d9539726d28103
+ 3ab97a491b334616b5320f00b70e5e3620d36e5286b74ca3
+ d3584dde26228442;
+ 91b3f9d10c39b07ae8f08ce7cee4758a386a99
+ 43e97dedfbe61e73
+ 7882cd09c2b9a80f34c0fde11c2481b11fc76bfa4dbf710a
+ 9e544e0c536ca1e040f9ad5b04140d98edabe08485290a4d
+ d9fe5001eec9f51d5650f640a1acd392b3eb4cb1edde5d31
+ b9c26d9e3edb786f;
+ 87d13b07398a1458c2c6b61dbdbc1cccada8c1
+ a0a9aabb6c4e3c35
+ ""
+ 54f8fb1ef61614c270295dfc0ca6551ca4bdb75359f91cb9d921056b7d
+ 3a35872aae6ecc5f2db7d75ba96b45d22646c61c41ecaa1be26c4685d0
+ 9f54725515309904;
+ e74fc9a9b37154ce6c0b396179d31f06a1dd59
+ 82cbc0d7cb23841d
+ a1ae8f4ae480cda98ad6cf2bacf6f9fd3f8213
+ 30c43f3df6c2b3fac7cbcf96523d4723f91801325eb8553236651c9678
+ 595e1b17cf4e6f603f4f37c5cc9f95960010ab062be907ea011276f6cc
+ 6cd3322bc4f3e0ec;
+ 8d73d192ee53b3f3ebd66ddd98cedbe88e245de25b1593b70f8601
+ 562d90a9b59ed034
+ ""
+ ""
+ ""
+ 39204a02c689b225;
+ a867642d25d54756fa5c47f16f64b837bb4926214211a1c696ba17
+ 2010abb433922a22
+ d9
+ ""
+ ""
+ 050a3b74030d78b6;
+ fd881519165eb9d85197a21cc34ac0d5ae7be8dbf98e4ffed2cf6b
+ 1372a5aa47b54fd9
+ ""
+ d7
+ f7
+ c80142d220c7ce79;
+ 0c70e117bf1cae71b3a56f0e7d839ea59cc783443d64f2ed6a29b9
+ 6856beca34fd6544
+ ""
+ bcf86b799e2a1681160ccf055f0fd3001da597a1406d465b
+ a317166b0030c8c02542e56149c7169f92667fa0f1825571
+ e1f6c6acb9532013;
+ 7b1419ea51cf858f938f6daafbd656445a09898eaa96ffc3d1d2e3
+ 1e4e34c94b8bfae6
+ 4825ecd75a66d88eedb969ffe07669845ebb7a24c69f13d0
+ 99f47166edf54538e88fbf433a7ff212085179e79771f6ee
+ bf9a3249cfaef471b99720132fe379a074cc10927ed689fc
+ f60b7355eb51cac1;
+ e7283ab178ef2b800d7b969da05780ffc1ba78c70dda7a4ca2a25e
+ 771702fb1901ecfc
+ ""
+ 8a959cb8e75079bb018ccc8c54f31b450e88f8e9002926ad0284c738f4
+ 287fa9c3540fc7adbfaf8a35cb932dbf3ec8be9b1c40ab18d34b1f82bf
+ a1789324aa8ffae5;
+ cb0f58a1e34c8b15ad930c1b627235a2cb84241986c251f5b70be2
+ 367f047265264e0d
+ a72efe8995e6c932a17eab511eddb8e4ba463c
+ 663035a6ae8a7a899e4279d54d03f0e0f3e961dcfd40088d5be74088e4
+ f2433dd6f072fe804e258d6facf08e8798a615510c1cd0f1283f7b172b
+ b4cee725242787cd;
+}
+
+rc2-pmac1 {
+ 60d7bcda163547d348b7551195e77022907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268ee
+ ""
+ 0e2341b111c8fa18;
+ ee533285a6ed810c9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a71
+ 30
+ 73e15def05b8727d;
+ c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085
+ 406a6136512061f7080cc07df0591d8fa21f2dd88374d8cd
+ 9a5cf16bab880541;
+ e8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731eb
+ fedd4705e505da1435dceaa7b1cc49ae1d50c3
+ 0573bcdf6c429f04;
+ 8201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26afa33498
+ ""
+ 5fc03971d7234498;
+ 29b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a
+ 22
+ d334d7d0dd6b420b;
+ 260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22b
+ b02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2a
+ 51b4652c5715fba8;
+ ebfa921451dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a874498ad0abef8bc4fcb70e27e98
+ ef1f0446b42fb144d44b6d00f06dc188d472a7
+ c288ffba6c151611;
+ 84e0c6f21195a3b9f4ae985511265febd11c16
+ ""
+ 2787117c93c78272;
+ 4720eef9eb1c8dd0b00951f284649016ed0045
+ 63
+ b9f64461b055f56d;
+ 31854bc78bf43966eb0cfa9138ddc399084456
+ 08fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126
+ dec9356cff25fd20;
+ b807e6daa089c3f9099c5ffb824173d7634c04
+ 226f30cbb7f0e4a973a8cd190107314717a774
+ f7be51b3498189d3;
+ 56f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9b
+ ""
+ 69b721838992f955;
+ c597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0cae9c
+ e0
+ 27583a3b6ce6eca6;
+ 21a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18c
+ bfe6effd1ff6778554acf1270485b203a3c1c4c967c0a458
+ 03e79dfa55f427b3;
+ cb948bdd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957
+ f4b03cf43e89957f9a3e8128f8743d16687b7b
+ 2eb16505976b0bf1;
+}
+
+rc2-ocb3 {
+ 60d7bcda163547d348b7551195e77022907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268ee
+ ee533285a6ed
+ ""
+ ""
+ ""
+ 581f918026a62a86;
+ 810c9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f1371206
+ 34c9519848a8
+ 77
+ ""
+ ""
+ 0f2f73159c7260d2;
+ ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07d
+ f0591d8fa21f
+ ""
+ 2d
+ af
+ f64c74ec46bb90b1;
+ d88374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3
+ e98787
+ ""
+ 31ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a8
+ 055814531dcb494c81bdd40c6b320ac9cdf3f6b48b3e62ca
+ 9624c68017513bf7;
+ 94476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52
+ ebfda19d0c
+ cc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33
+ d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605f
+ 7dbbed27e29a669ee60e79d868848e797cf8d585fa877eef
+ b181420c050f46bb;
+ aee2b03fb648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f8f28523c03d4de1600
+ 157846b710ee
+ ""
+ 72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d
+ d2edbee66b1039b346ad18f087e5712227159fa306a398b03c5805ebaa
+ 7f3a208c993f1401;
+ 57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f
+ 768281e040a9
+ b9a222bd689aef66f5306ceb0c6b08ac8b0a22
+ 260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe836
+ a7d224261bc9eed46f062bad5ce6acf20db49e5efa965da235a6cbfcf2
+ 800f8ff9dbcbfcfb;
+ 8131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451
+ dcd1af5813b7
+ ""
+ ""
+ ""
+ abdbde1d369f81cf;
+ 0d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b6d
+ 00f06dc188d4
+ 72
+ ""
+ ""
+ 8a82cb9899ea8c5e;
+ a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717
+ a77456f3ff66
+ ""
+ 9c
+ e6
+ 0d8c6497b6eae6d2;
+ 732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b480aa3a4c84c
+ ef64f6
+ ""
+ c9b53bf8f957f4b03cf43e89957f9a3e8128f8743d16687b
+ 49ef16eee0810eecd3e8dab4f26ab52a367325b186d5829e
+ 1703b30f19f8fd57;
+ 7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a5718fd25014107c8e7d715a92add9589d1
+ f5c054b2d9
+ 83514605ec590294a319b9802068a9f891bc5ba5afabf8c3
+ 122d12d7ff3c41122d70d17d4569eaff59a332ba58d5d558
+ 6d390ba093cfe6c87e7d319eb6aa78bad09fc27ef0901b6e
+ 44577228a64debfa;
+ 9bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4563d405e51881e99027b8ab9aea3ccf860b0009740763d96836c5f87b95460938de1288c69d80ea12ff4bb5f069b8a
+ 2e86041c1b9f
+ ""
+ c214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c3680
+ 7c69cf94aeefeb59424b9cea58a906052733cd4218668705ab2853691c
+ e4f0891347b99255;
+ 0d9645563a308ba60076817523bd2abf1261b089d8f23a9c2835076a23faac2cdd67771cc667a8331f0a170b66283e4f834a06148f302c3973accd56f6f24e33958b8c2e2352fd61e4fa8fec816ac861a8b33779f09e7a10fc02a8f48afa3080ee119a52a9a817e4f2b94b0820cab383a8cffeea7c4863
+ 15799dc875fb
+ a578c8ec4837898a92142b5b0677da1ac27311
+ 7b45bcfff5d5f8b6fde2893232a9f81d14517ffae475f6b94a43a67b3d
+ 625cdc216187b9b9c5fa391d280bfa6b305ba1cb1fdd3724d8a72e1ac7
+ 519207d1413a1b4d;
+ 380d2f9aaafe2dd721c0095c88088476892114
+ 50ba8095ffab
+ ""
+ ""
+ ""
+ 06cfa98d411047e9;
+ 1eaadf66fd22ac1976063e113ab61f813e28a1
+ 397a7974a1d7
+ f4
+ ""
+ ""
+ 175d23bbcafb83d7;
+ 220c785fe426a5a0e80f678d404147842941fe
+ effdc2eb44dc
+ ""
+ 8c
+ 58
+ 5468b08a313669e1;
+ 0d5e8f444f7f4e0c893959b74dc23a7bb40e7e
+ 0013e5
+ ""
+ 150686d2301b43a15a84e81d7f5cedaa49e2414ebf47970e
+ ad2f294aef829753411546662ae01fb4b8c949c124b4a49b
+ 6d43da0bc3eae79d;
+ 560475cff206877de69146acc3ab6cf8556b7a
+ a776945948
+ d1b8834df2196c92ec1718dcdeee0d52d9539726d2810391
+ b3f9d10c39b07ae8f08ce7cee4758a386a9943e97dedfbe6
+ 52df344f60bb655ce1efadd2bd8aadb58cba837a06a85693
+ dfd8c77383ca55f1;
+ 1e737882cd09c2b9a80f34c0fde11c2481b11f
+ c76bfa4dbf71
+ ""
+ 0a9e544e0c536ca1e040f9ad5b04140d98edabe08485290a4d87d13b07
+ 8be902be354731e8231299e1b2dedaae4690ecf8089199e6cec95b6123
+ 0f45a8eb852e5baa;
+ 398a1458c2c6b61dbdbc1cccada8c1a0a9aabb
+ 6c4e3c3554f8
+ fb1ef61614c270295dfc0ca6551ca4bdb75359
+ f91cb9d921056b7de74fc9a9b37154ce6c0b396179d31f06a1dd5982cb
+ 3fb468bbadc6a29bd6281da179066d2ade7be03df9c6b383c8e8c13546
+ b26515dac888c01c;
+ c0d7cb23841da1ae8f4ae480cda98ad6cf2bacf6f9fd3f821330c4
+ 3f3df6c2b3fa
+ ""
+ ""
+ ""
+ 34bd44dbfedfadb7;
+ c7cbcf96523d4723f91801325eb8553236651c96788d73d192ee53
+ b3f3ebd66ddd
+ 98
+ ""
+ ""
+ 30e8cb9e8b9c5270;
+ cedbe88e245de25b1593b70f8601562d90a9b59ed034a867642d25
+ d54756fa5c47
+ ""
+ f1
+ 0b
+ a2ccd20dc938026f;
+ 6f64b837bb4926214211a1c696ba172010abb433922a22d9fd8815
+ 19165e
+ ""
+ b9d85197a21cc34ac0d5ae7be8dbf98e4ffed2cf6b1372a5
+ 68cd0332b59dd009fe414fedbaa6e5db5617a72662f17e00
+ e56e28e0835cfe53;
+ aa47b54fd9d70c70e117bf1cae71b3a56f0e7d839ea59cc783443d
+ 64f2ed6a29
+ b96856beca34fd6544bcf86b799e2a1681160ccf055f0fd3
+ 001da597a1406d465b7b1419ea51cf858f938f6daafbd656
+ 14eba6942ae06ed78cf099b84112f9a14ef047a66bc60759
+ 8cf160f02394665d;
+ 445a09898eaa96ffc3d1d2e31e4e34c94b8bfae64825ecd75a66d8
+ 8eedb969ffe0
+ ""
+ 7669845ebb7a24c69f13d099f47166edf54538e88fbf433a7ff2120851
+ 6d2c904a5679e677bb5388b0fd803942da8009ba69144d90adeebbbd9e
+ 9bc08b7a451dab64;
+ 79e79771f6eee7283ab178ef2b800d7b969da05780ffc1ba78c70d
+ da7a4ca2a25e
+ 771702fb1901ecfc8a959cb8e75079bb018ccc
+ 8c54f31b450e88f8e9002926ad0284c738f4cb0f58a1e34c8b15ad930c
+ 7e6523063d93c71b5e3843e7e1db47185be88cd6e59983a344ccaa55f3
+ de2d08e85152d02e;
+}
+
+rc2-ocb3-mct {
+ 16 cf8c7167477a5451;
+ 14 f7b6b2058ca5db46;
+ 12 249d762b7fef3e0a;
+ 10 a6d5f268d2dc063d;
+ 8 760827c7117d67ef;
+ 6 4acbb3854f8a4d2c;
+ 4 9165027bf9b60335;
+ 16 06ec3efc4156;
+ 14 0b3b19c5b0a6;
+ 12 8651074d6d12;
+ 10 f2c5ce719be9;
+ 8 d6646daf8e75;
+ 6 70c48ce7d192;
+ 4 61903ea2f3fe;
+ 16 a9049697;
+ 14 e4cdf5af;
+ 12 5571a44b;
+ 10 a9e735fa;
+ 8 4179cf26;
+ 6 4a83d2cf;
+ 4 f50be88c;
+}
dc49db1375a5584f6485b413b5f12baf 2f42b3b70369fc92 65c178b284d197cc;
5269f149d41ba0152497574d7f153125 65c178b284d197cc eb44e415da319824;
}
+
+rc5-cmac {
+ 60d7bcda163547d348b7551195e77022907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268eeee533285a6ed810c9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057
+ ""
+ daf5b15f8e1e563c;
+ acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26afa3349829b94586306fed5415
+ 4f
+ da179047660f232b;
+ 8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a
+ 96ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b9
+ 0bc5dfb1ac40f05c;
+ 7e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a8744
+ 98ad0abef8bc4fcb70e27e98ef1f0446b42fb1
+ ba244301c8380eac;
+ 44d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff677
+ ""
+ 4c21b877018c36b9;
+ 8554acf1270485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a5718fd25014107c8e7d715a92add9589d1f5c054b2d983514605ec590294a319b9802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70d1
+ 7d
+ 3806f9d4de532103;
+ 4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4563d405e51881e99027b8ab9aea3ccf860b0009740763d96836c5f87b95460938de1288c69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c36800d9645563a308ba60076817523bd2abf1261b089d8f23a9c2835076a23faac2cdd67771cc667a8331f0a170b66283e4f834a06148f302c
+ 3973accd56f6f24e33958b8c2e2352fd61e4fa8fec816ac8
+ a23a44e7657e986c;
+ 61a8b33779f09e7a10fc02a8f48afa3080ee119a52a9a817e4f2b94b0820cab383a8cffeea7c486315799dc875fba578c8ec4837898a92142b5b0677da1ac273117b45bcfff5d5f8b6fde2893232a9f81d14517ffae475f6b94a43a67b3d380d2f9aaafe2dd721c0095c8808847689211450ba8095ffab1eaadf66fd22ac1976063e113ab61f813e28a1397a7974a1d7f4220c785fe426a5a0e80f678d404147842941feeffdc2eb44dc8c0d5e8f444f7f4e0c893959b74dc23a7bb40e7e0013e5150686d2301b43a15a84e81d7f5cedaa49e2414ebf47970e560475cf
+ f206877de69146acc3ab6cf8556b7aa7769459
+ e4b7b2e862a7a773;
+ 48d1b8834df2196c92ec1718dcdeee0d52d9539726d2810391b3f9d10c39b07ae8f08ce7cee475
+ ""
+ f0b878ae4b245d7a;
+ 8a386a9943e97dedfbe61e737882cd09c2b9a80f34c0fde11c2481b11fc76bfa4dbf710a9e544e
+ 0c
+ 6f07948d34c807ed;
+ 536ca1e040f9ad5b04140d98edabe08485290a4d87d13b07398a1458c2c6b61dbdbc1cccada8c1
+ a0a9aabb6c4e3c3554f8fb1ef61614c270295dfc0ca6551c
+ 3b56f732d29bcda8;
+ a4bdb75359f91cb9d921056b7de74fc9a9b37154ce6c0b396179d31f06a1dd5982cbc0d7cb2384
+ 1da1ae8f4ae480cda98ad6cf2bacf6f9fd3f82
+ 28c46ab756a75864;
+ 1330c43f3df6c2b3fac7cbcf96523d4723f91801325eb8553236651c96788d73d192ee53b3f3ebd66ddd98cedbe88e245de25b1593b70f8601562d90a9b59ed034a867642d25d54756fa5c47f1
+ ""
+ 08523dfcb089cd8c;
+ 6f64b837bb4926214211a1c696ba172010abb433922a22d9fd881519165eb9d85197a21cc34ac0d5ae7be8dbf98e4ffed2cf6b1372a5aa47b54fd9d70c70e117bf1cae71b3a56f0e7d839ea59c
+ c7
+ 26a7e390109474a1;
+ 83443d64f2ed6a29b96856beca34fd6544bcf86b799e2a1681160ccf055f0fd3001da597a1406d465b7b1419ea51cf858f938f6daafbd656445a09898eaa96ffc3d1d2e31e4e34c94b8bfae648
+ 25ecd75a66d88eedb969ffe07669845ebb7a24c69f13d099
+ 841195a80291401c;
+ f47166edf54538e88fbf433a7ff212085179e79771f6eee7283ab178ef2b800d7b969da05780ffc1ba78c70dda7a4ca2a25e771702fb1901ecfc8a959cb8e75079bb018ccc8c54f31b450e88f8
+ e9002926ad0284c738f4cb0f58a1e34c8b15ad
+ 029a65f6ecedeaec;
+}
+
+rc5-ccm {
+ 60d7bcda163547d348b7551195e77022907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268eeee533285a6ed810c9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057
+ acc876
+ ""
+ ""
+ ""
+ 7c254f77;
+ 38f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f8f28
+ 523c03
+ d4
+ ""
+ ""
+ 1bee7cd9;
+ de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca3
+ 38527e
+ ""
+ f1
+ b4
+ 2a4035c8;
+ 9b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa
+ 69a4cd5214
+ 7ed12ca986981a874498ad0abef8bc4fcb70e27e98ef1f04
+ 46b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9
+ 27b471cdc900d7c1cecdbccbe0c791d0894881688285dc18
+ 0c52bf2c8519e396;
+ f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0cae9ce021
+ a5f1fa4ffa
+ 91544485f1a1258b2b9b8f0911e32d65cc1770
+ a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967c0a458cb948b
+ 4c97911b3e34ed74ca84d41573f434210e43911778a77caa1bb64b5d52
+ 329a8ae6ba7b6150;
+ dd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a5718fd25014107c8e7d715a92add9589d1f5c054b2d983514605ec590294a319b9802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe079753ee1a
+ 957eb6
+ ""
+ ""
+ ""
+ 83c54227;
+ d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4563d405e51881e99027b8ab9aea3ccf860b0009740763d96836c5f87b95460938de1288c69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c36800d9645563a308ba60076817523bd2abf1261b089d8f23a9c2835076a23faac2cdd67771cc667a8331f0a170b66283e4f834a06148f302c3973accd56f6f24e33958b8c2e2352fd61e4fa8fec81
+ 6ac861
+ a8
+ ""
+ ""
+ d11cd472;
+ b33779f09e7a10fc02a8f48afa3080ee119a52a9a817e4f2b94b0820cab383a8cffeea7c486315799dc875fba578c8ec4837898a92142b5b0677da1ac273117b45bcfff5d5f8b6fde2893232a9f81d14517ffae475f6b94a43a67b3d380d2f9aaafe2dd721c0095c8808847689211450ba8095ffab1eaadf66fd22ac1976063e113ab61f813e28a1397a7974a1d7f4220c785fe426a5a0e80f678d404147842941feeffdc2eb44dc8c0d5e8f444f7f4e0c893959b74dc23a7bb40e7e0013e5150686d2301b43a15a84e81d7f5cedaa49e2414ebf47970e560475cff206
+ 877de6
+ ""
+ 91
+ d7
+ 75a2a5f9;
+ 46acc3ab6cf8556b7aa776945948d1b8834df2196c92ec1718dcdeee0d52d9539726d2810391b3f9d10c39b07ae8f08ce7cee4758a386a9943e97dedfbe61e737882cd09c2b9a80f34c0fde11c2481b11fc76bfa4dbf710a9e544e0c536ca1e040f9ad5b04140d98edabe08485290a4d87d13b07398a1458c2c6b61dbdbc1cccada8c1a0a9aabb6c4e3c3554f8fb1ef61614c270295dfc0ca6551ca4bdb75359f91cb9d921056b7de74fc9a9b37154ce6c0b396179d31f06a1dd5982cbc0d7cb23841da1ae8f4ae480cda98ad6cf2bacf6f9fd3f821330c43f3df6c2b3
+ fac7cbcf96
+ 523d4723f91801325eb8553236651c96788d73d192ee53b3
+ f3ebd66ddd98cedbe88e245de25b1593b70f8601562d90a9
+ 740ab29287b8db09e16309ab92186c430c2c71905ef788db
+ 16ed39d411395c7f;
+ b59ed034a867642d25d54756fa5c47f16f64b837bb4926214211a1c696ba172010abb433922a22d9fd881519165eb9d85197a21cc34ac0d5ae7be8dbf98e4ffed2cf6b1372a5aa47b54fd9d70c70e117bf1cae71b3a56f0e7d839ea59cc783443d64f2ed6a29b96856beca34fd6544bcf86b799e2a1681160ccf055f0fd3001da597a1406d465b7b1419ea51cf858f938f6daafbd656445a09898eaa96ffc3d1d2e31e4e34c94b8bfae64825ecd75a66d88eedb969ffe07669845ebb7a24c69f13d099f47166edf54538e88fbf433a7ff212085179e79771f6eee7283a
+ b178ef2b80
+ 0d7b969da05780ffc1ba78c70dda7a4ca2a25e
+ 771702fb1901ecfc8a959cb8e75079bb018ccc8c54f31b450e88f8e900
+ b630304c8082405cd416ec56b4b32cd188cb81075a1df8e7ded7042e84
+ 15c392aa9df0ff73;
+ 2926ad0284c738f4cb0f58a1e34c8b15ad930c1b627235a2cb84241986c251f5b70be2367f0472
+ 65264e
+ ""
+ ""
+ ""
+ 5c63c12d;
+ 0da72efe8995e6c932a17eab511eddb8e4ba463c663035a6ae8a7a899e4279d54d03f0e0f3e961
+ dcfd40
+ 08
+ ""
+ ""
+ 8ec0a5a4;
+ 8d5be74088e4097efb0368c7e2f431ee6988cf2a0e9ebeb3de79c4f86c9e4fba61339d6d907eab
+ 7707ca
+ ""
+ 48
+ 61
+ d74da629;
+ ff5ba1ae93d16225d469de5747bc1addf5748729720a320fe14fd29cfc59314fe2079c0a2535de
+ d56112d6e3
+ d33dcf7c71cd7d130323794e3da84a9df69703a9caf02d2a
+ 8f57ac71e554a6850d55882f8c7ae6994fc8528bd18c374f
+ 12ebdfc275cb1ad1926629dec9765ecde238384b6b77aed3
+ 91dd4e2e2acf63f7;
+ c43581d2f72a89584a2404a059f7f99c7241a0c879d6d4455b382a9ce757b3e7a1d07585ad9d7e
+ a9c7c9cf54
+ f3bc6d94238ab56d738e02abd651477cd726d6
+ f3ebcd6fadeab50906642a7de6496247060e7be3632ed9bd94bb42f45a
+ a0cbde9a036ed8857dec5ad4dce61b29ec4a9c304fe386afefe3aee97f
+ 84fbd4d0f0710fea;
+ 8733b2cd2df9d1d905cfdb29983050d6bcdb686a0c897031ad09a5b8fa687ec3bad8e18dc2ad361f1e226e78876cd35f86c639733c5cd84aed8aaebabb7e0f24edfd9710b7bca91b612ea37fc5
+ cc09f7
+ ""
+ ""
+ ""
+ b8580130;
+ f62f66b423fcd2dec5de24d264f2c839839c1b06319f687dbc68d9f07fd41ccb4f8cde8de201ec2680332bbded4883deea0b58b54bdd13c17ef292b0ded3caeb5e57fd21df10bc6186265ee6ea
+ 45907d
+ e6
+ ""
+ ""
+ aa6fedbc;
+ cb822fb2ef953aea358a03e0fce2e1b9511bd332c86e67f123377a8f0256b8dcc73ae1b3c6cd3f104e3cb24284cfed17811d64d492d39ea7496993a25b072945d83f923e66b0a6689cf0969c00
+ 3a8fca
+ ""
+ 80
+ b5
+ 0b3d21e2;
+ e322a4b1bf050c1220450433efb6b6d8a2d820cf27a64b9d47f636845dac557bb3e75f3a18fb8e173416867fcd0ee78ddd9236beec76d55ed58b10f91d07a037791ab96e83c4bf2fb5b205e592
+ c172a5cbc1
+ 9456c95c1bea6079f3867e52d663cb3884b2a0a8ff825df7
+ 52423f3179bfeb89eca385f20ddce5f1f23564672e370ffc
+ 704a2f85040f89ae682fc9fe222d1514c8a6ee4c83621978
+ bd37c7f24ffd34dd;
+ 37d400a31e8aac1d426ce10df73c5ee478b3b63d91024780e974a8a2a0e7a36f84ab1286b627e7d01b38a84a6de738721ed80fd0d7f69fa658abb5a440d304128719b541a9451cead18e4c61d9
+ 3d1f8fcc53
+ 574427767396322b3bf7d02cec05093696cec0
+ 7591ada462271b1d1519eedde0df37a330fe8c22ebd77705917b7e32ae
+ a81b6872abcb10bf73091054448aa06f5713d2da96a21467a86272aae7
+ 3acb5a6ac60a7d69;
+}
+
+rc5-eax {
+ 60d7bcda163547d348b7551195e77022907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268eeee533285a6ed810c9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057
+ ""
+ ""
+ ""
+ ""
+ b6a3c65665d9698f;
+ acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26afa3349829b94586306fed5415
+ 4f
+ ""
+ ""
+ ""
+ 28e0ed64beb3636e;
+ 8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a
+ ""
+ 96
+ ""
+ ""
+ 4e86273646b6d548;
+ ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b9
+ ""
+ ""
+ 70
+ e2
+ b61886a4345f760a;
+ e47479a684b5aefa69a4cd52147ed12ca986981a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107
+ 314717a77456f3ff
+ 669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9b
+ c597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc
+ c1032a72ac5e8845a7d27deae33795ccc3bf3caf3e3cb94d
+ ac40d28502442851;
+ 0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397abfaf529ee41cf
+ 9a05c7efedef34
+ 01539c51d2a90bbf7f1bfc338ab0ef5746ea8f
+ dcccd213e33f7e8a5718fd25014107c8e7d715a92add9589d1f5c054b2
+ bf3cf0b9900f40e42643c19226af6cff9d221051ab7a52e22bdb0343d0
+ 19e314d1c9556ec7;
+ d983514605ec590294a319b9802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4563d405e51881e99027b8ab9aea3ccf860b0009740763d96836c5f87b95460938de1288c69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c36800d9645563a308ba60076817523bd2abf1261
+ ""
+ ""
+ ""
+ ""
+ 3c01672989b90b3d;
+ b089d8f23a9c2835076a23faac2cdd67771cc667a8331f0a170b66283e4f834a06148f302c3973accd56f6f24e33958b8c2e2352fd61e4fa8fec816ac861a8b33779f09e7a10fc02a8f48afa3080ee119a52a9a817e4f2b94b0820cab383a8cffeea7c486315799dc875fba578c8ec4837898a92142b5b0677da1ac273117b45bcfff5d5f8b6fde2893232a9f81d14517ffae475f6b94a43a67b3d380d2f9aaafe2dd721c0095c8808847689211450ba8095ffab1eaadf66fd22ac1976063e113ab61f813e28a1397a7974a1d7f4220c785fe426a5a0e80f678d404147
+ 84
+ ""
+ ""
+ ""
+ ec812e10e0061171;
+ 2941feeffdc2eb44dc8c0d5e8f444f7f4e0c893959b74dc23a7bb40e7e0013e5150686d2301b43a15a84e81d7f5cedaa49e2414ebf47970e560475cff206877de69146acc3ab6cf8556b7aa776945948d1b8834df2196c92ec1718dcdeee0d52d9539726d2810391b3f9d10c39b07ae8f08ce7cee4758a386a9943e97dedfbe61e737882cd09c2b9a80f34c0fde11c2481b11fc76bfa4dbf710a9e544e0c536ca1e040f9ad5b04140d98edabe08485290a4d87d13b07398a1458c2c6b61dbdbc1cccada8c1a0a9aabb6c4e3c3554f8fb1ef61614c270295dfc0ca6551c
+ ""
+ a4
+ ""
+ ""
+ f87f9705308d2757;
+ bdb75359f91cb9d921056b7de74fc9a9b37154ce6c0b396179d31f06a1dd5982cbc0d7cb23841da1ae8f4ae480cda98ad6cf2bacf6f9fd3f821330c43f3df6c2b3fac7cbcf96523d4723f91801325eb8553236651c96788d73d192ee53b3f3ebd66ddd98cedbe88e245de25b1593b70f8601562d90a9b59ed034a867642d25d54756fa5c47f16f64b837bb4926214211a1c696ba172010abb433922a22d9fd881519165eb9d85197a21cc34ac0d5ae7be8dbf98e4ffed2cf6b1372a5aa47b54fd9d70c70e117bf1cae71b3a56f0e7d839ea59cc783443d64f2ed6a29b9
+ ""
+ ""
+ 68
+ 2c
+ ecb3af42ad5aaf5c;
+ 56beca34fd6544bcf86b799e2a1681160ccf055f0fd3001da597a1406d465b7b1419ea51cf858f938f6daafbd656445a09898eaa96ffc3d1d2e31e4e34c94b8bfae64825ecd75a66d88eedb969ffe07669845ebb7a24c69f13d099f47166edf54538e88fbf433a7ff212085179e79771f6eee7283ab178ef2b800d7b969da05780ffc1ba78c70dda7a4ca2a25e771702fb1901ecfc8a959cb8e75079bb018ccc8c54f31b450e88f8e9002926ad0284c738f4cb0f58a1e34c8b15ad930c1b627235a2cb84241986c251f5b70be2367f047265264e0da72efe8995e6c932
+ a17eab511eddb8e4
+ ba463c663035a6ae8a7a899e4279d54d03f0e0f3e961dcfd
+ 40088d5be74088e4097efb0368c7e2f431ee6988cf2a0e9e
+ 097489eca92aa5642b549cfac254a0084e6392328b287f68
+ 1e35efa371fa0754;
+ beb3de79c4f86c9e4fba61339d6d907eab7707ca48ff5ba1ae93d16225d469de5747bc1addf5748729720a320fe14fd29cfc59314fe2079c0a2535ded56112d6e3d33dcf7c71cd7d130323794e3da84a9df69703a9caf02d2a8f57ac71e554a6850d55882f8c7ae6994fc8528bd18c374fc43581d2f72a89584a2404a059f7f99c7241a0c879d6d4455b382a9ce757b3e7a1d07585ad9d7ea9c7c9cf54f3bc6d94238ab56d738e02abd651477cd726d6f3ebcd6fadeab50906642a7de6496247060e7be3632ed9bd94bb42f45a8733b2cd2df9d1d905cfdb29983050d6
+ bcdb686a0c8970
+ 31ad09a5b8fa687ec3bad8e18dc2ad361f1e22
+ 6e78876cd35f86c639733c5cd84aed8aaebabb7e0f24edfd9710b7bca9
+ faaae6078a435e40c355d6cb7522b57d1d2041d016be50c0499a94a4c9
+ d37dacc2ee37665c;
+ 1b612ea37fc5cc09f7f62f66b423fcd2dec5de24d264f2c839839c1b06319f687dbc68d9f07fd4
+ ""
+ ""
+ ""
+ ""
+ 8e0d69b365dcd5f0;
+ 1ccb4f8cde8de201ec2680332bbded4883deea0b58b54bdd13c17ef292b0ded3caeb5e57fd21df
+ 10
+ ""
+ ""
+ ""
+ 70b4543f8437c930;
+ bc6186265ee6ea45907de6cb822fb2ef953aea358a03e0fce2e1b9511bd332c86e67f123377a8f
+ ""
+ 02
+ ""
+ ""
+ 7b962a2f0a36c218;
+ 56b8dcc73ae1b3c6cd3f104e3cb24284cfed17811d64d492d39ea7496993a25b072945d83f923e
+ ""
+ ""
+ 66
+ d3
+ e3934e8cf3dd1e43;
+ b0a6689cf0969c003a8fca80e322a4b1bf050c1220450433efb6b6d8a2d820cf27a64b9d47f636
+ 845dac557bb3e75f
+ 3a18fb8e173416867fcd0ee78ddd9236beec76d55ed58b10
+ f91d07a037791ab96e83c4bf2fb5b205e592c172a5cbc194
+ 1c11e3e723c447062953918da6c2935a8f736ba211e02110
+ 26cf3b89bb9216cc;
+ 56c95c1bea6079f3867e52d663cb3884b2a0a8ff825df752423f3179bfeb89eca385f20ddce5f1
+ f23564672e370f
+ fc37d400a31e8aac1d426ce10df73c5ee478b3
+ b63d91024780e974a8a2a0e7a36f84ab1286b627e7d01b38a84a6de738
+ 76d660c82fe87ec1fe0ae671550a17ecff0c9e771db2949c1b786f1cf2
+ 740fccf37358c969;
+ 721ed80fd0d7f69fa658abb5a440d304128719b541a9451cead18e4c61d93d1f8fcc53574427767396322b3bf7d02cec05093696cec07591ada462271b1d1519eedde0df37a330fe8c22ebd777
+ ""
+ ""
+ ""
+ ""
+ cfff0e086dd13bf8;
+ 05917b7e32ae88f45a34a8ba3037235e19a394be4d26ce47317d8087684456b4cfc5555e925e3e7b2ebc829b2d0505ea617b0ca9531bcdb96040d39040e632d562643ccb64286303040fcaf679
+ e9
+ ""
+ ""
+ ""
+ 1e93f551fac620d8;
+ 14eaddc05af8843ce6a427b99a5dc266de31c09165237eeefe4b58cc034b9f099f04678c2a9da898b39324cd3087a651014f6796f9c4881d89e127e62221e47e57badd678d490c2f320ff8fb1c
+ ""
+ 42
+ ""
+ ""
+ ea6e9288b9febdb3;
+ 761bd439f3e96dc0ed1d5b2169912af1a4e2c533c52ba3e8c71c23a089e231480aa63c484fb34bd522397f102cb8ecf4f64e329884fe73be257a753b38200bc23f94a079bde2dd98d813655daf
+ ""
+ ""
+ a1
+ 83
+ 409170cbacd6adbb;
+ 5b85419d15c41a5153cce5d0e8c8702db2ba11927589678d4f7b8fcfad4818c411f15f452300903874f9a532ee46496ae753a2340af7b91f9632fc5ae71ae18b40de751ab6b6761ca16434a993
+ 5e466e11c1cb072f
+ 32a59c313dba3db646ae909a096697d9a7b0556463ff1126
+ ebc43263391424d02739d0787e804d8f1dccf6c897a8a484
+ c9f82dea0b1b5fd479b0aeb37b717817455887a199312aa9
+ 4e1d9e542a78d512;
+ 31324324041b5302ccd501b538bd03d5cb5c90d1fd3f7d2be187a787032c79ed900764ee4ce1d3fc042c084f7d8c0c48ad7d6f1eabd0fd1ec24a88f26734d5c8d92dbd873a8fe113090d401bea
+ 4d28ff49f10ff5
+ 93adc258e091abd31b62dd1735158f98765970
+ acc6602da063aae01a2a199d3a4f37a5f062d216d2053a83b5d3a0488a
+ a9dc22dc5d57626720b7c1260c63dae59cbad790ac527d5a26e7d943dd
+ 86f8915e2fdee1e3;
+}
+
+rc5-gcm {
+ 60d7bcda163547d348b7551195e77022907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268eeee533285a6ed810c9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057
+ ""
+ ""
+ ""
+ ""
+ e2f61b7a5d2e1c0a;
+ acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26afa3349829b94586306fed5415
+ 4f
+ ""
+ ""
+ ""
+ 8054b24c29fed688;
+ 8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a
+ ""
+ 96
+ ""
+ ""
+ db8e85bf23f737de;
+ ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b9
+ ""
+ ""
+ 70
+ 17
+ 7c5e0036fc6b0768;
+ e47479a684b5aefa69a4cd52147ed12ca986981a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107
+ 314717a77456f3ff
+ 669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9b
+ c597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc
+ 3549c431f3e7576dfcaf3130ec16f3f548704d727782677b
+ 28148be1172ee6bf;
+ 0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397abfaf529ee41cf
+ 9a05c7ef
+ edef3401539c51d2a90bbf
+ 7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a5718fd25014107c8e7d715a92add
+ 3ff03565f741b63e12a647f755353af479b9f3ddfa1d50ff1540221f0bbb5c8b1e
+ 81f81acac5371be7;
+ 9589d1f5c054b2d983514605ec590294a319b9802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4563d405e51881e99027b8ab9aea3ccf860b0009740763d96836c5f87b95460938de1288c69d80ea1
+ 2ff4bb5f069b8a
+ 2e86041c1b9fc214e9ca2186ddf1f6a7a3aa7e
+ 740da967828e3604b35b15ffaa6c36800d9645563a308ba60076817523
+ b0b28a3e099aecdda0b6756d2340184ab16df2c8cee22003ec3b783500
+ 61d50b3d4e61fa34;
+ bd2abf1261b089d8f23a9c2835076a23faac2cdd67771cc667a8331f0a170b66283e4f834a06148f302c3973accd56f6f24e33958b8c2e2352fd61e4fa8fec816ac861a8b33779f09e7a10fc02a8f48afa3080ee119a52a9a817e4f2b94b0820cab383a8cffeea7c486315799dc875fba578c8ec4837898a92142b5b0677da1ac273117b45bcfff5d5f8b6fde2893232a9f81d14517ffae475f6b94a43a67b3d380d2f9aaafe2dd721c0095c8808847689211450ba8095ffab1eaadf66fd22ac1976063e113ab61f813e28a1397a7974a1d7f4220c785fe426a5a0e80f
+ ""
+ ""
+ ""
+ ""
+ 6133d10511794867;
+ 678d404147842941feeffdc2eb44dc8c0d5e8f444f7f4e0c893959b74dc23a7bb40e7e0013e5150686d2301b43a15a84e81d7f5cedaa49e2414ebf47970e560475cff206877de69146acc3ab6cf8556b7aa776945948d1b8834df2196c92ec1718dcdeee0d52d9539726d2810391b3f9d10c39b07ae8f08ce7cee4758a386a9943e97dedfbe61e737882cd09c2b9a80f34c0fde11c2481b11fc76bfa4dbf710a9e544e0c536ca1e040f9ad5b04140d98edabe08485290a4d87d13b07398a1458c2c6b61dbdbc1cccada8c1a0a9aabb6c4e3c3554f8fb1ef61614c27029
+ 5d
+ ""
+ ""
+ ""
+ 25ff252aec8e0979;
+ fc0ca6551ca4bdb75359f91cb9d921056b7de74fc9a9b37154ce6c0b396179d31f06a1dd5982cbc0d7cb23841da1ae8f4ae480cda98ad6cf2bacf6f9fd3f821330c43f3df6c2b3fac7cbcf96523d4723f91801325eb8553236651c96788d73d192ee53b3f3ebd66ddd98cedbe88e245de25b1593b70f8601562d90a9b59ed034a867642d25d54756fa5c47f16f64b837bb4926214211a1c696ba172010abb433922a22d9fd881519165eb9d85197a21cc34ac0d5ae7be8dbf98e4ffed2cf6b1372a5aa47b54fd9d70c70e117bf1cae71b3a56f0e7d839ea59cc783443d
+ ""
+ 64
+ ""
+ ""
+ 68c3eb5a75e3992e;
+ f2ed6a29b96856beca34fd6544bcf86b799e2a1681160ccf055f0fd3001da597a1406d465b7b1419ea51cf858f938f6daafbd656445a09898eaa96ffc3d1d2e31e4e34c94b8bfae64825ecd75a66d88eedb969ffe07669845ebb7a24c69f13d099f47166edf54538e88fbf433a7ff212085179e79771f6eee7283ab178ef2b800d7b969da05780ffc1ba78c70dda7a4ca2a25e771702fb1901ecfc8a959cb8e75079bb018ccc8c54f31b450e88f8e9002926ad0284c738f4cb0f58a1e34c8b15ad930c1b627235a2cb84241986c251f5b70be2367f047265264e0da72e
+ ""
+ ""
+ fe
+ ca
+ 187921ec9e1052c1;
+ 8995e6c932a17eab511eddb8e4ba463c663035a6ae8a7a899e4279d54d03f0e0f3e961dcfd40088d5be74088e4097efb0368c7e2f431ee6988cf2a0e9ebeb3de79c4f86c9e4fba61339d6d907eab7707ca48ff5ba1ae93d16225d469de5747bc1addf5748729720a320fe14fd29cfc59314fe2079c0a2535ded56112d6e3d33dcf7c71cd7d130323794e3da84a9df69703a9caf02d2a8f57ac71e554a6850d55882f8c7ae6994fc8528bd18c374fc43581d2f72a89584a2404a059f7f99c7241a0c879d6d4455b382a9ce757b3e7a1d07585ad9d7ea9c7c9cf54f3bc6d
+ 94238ab56d738e02
+ abd651477cd726d6f3ebcd6fadeab50906642a7de6496247
+ 060e7be3632ed9bd94bb42f45a8733b2cd2df9d1d905cfdb
+ ce458e557a153a69bff6fe3c4489c7a06e87dbbe31777fb2
+ b90acc3a3f31e693;
+ 29983050d6bcdb686a0c897031ad09a5b8fa687ec3bad8e18dc2ad361f1e226e78876cd35f86c639733c5cd84aed8aaebabb7e0f24edfd9710b7bca91b612ea37fc5cc09f7f62f66b423fcd2dec5de24d264f2c839839c1b06319f687dbc68d9f07fd41ccb4f8cde8de201ec2680332bbded4883deea0b58b54bdd13c17ef292b0ded3caeb5e57fd21df10bc6186265ee6ea45907de6cb822fb2ef953aea358a03e0fce2e1b9511bd332c86e67f123377a8f0256b8dcc73ae1b3c6cd3f104e3cb24284cfed17811d64d492d39ea7496993a25b072945d83f923e66b0a6
+ 689cf096
+ 9c003a8fca80e322a4b1bf
+ 050c1220450433efb6b6d8a2d820cf27a64b9d47f636845dac557bb3e75f3a18fb
+ 17a5e823d237aa01c73f6414d39d44b2f564a0dd3f1a07a2899a8051d1f0df8f39
+ 36f636bbcbf9dd90;
+ 8e173416867fcd0ee78ddd9236beec76d55ed58b10f91d07a037791ab96e83c4bf2fb5b205e592c172a5cbc19456c95c1bea6079f3867e52d663cb3884b2a0a8ff825df752423f3179bfeb89eca385f20ddce5f1f23564672e370ffc37d400a31e8aac1d426ce10df73c5ee478b3b63d91024780e974a8a2a0e7a36f84ab1286b627e7d01b38a84a6de738721ed80fd0d7f69fa658abb5a440d304128719b541a9451cead18e4c61d93d1f8fcc53574427767396322b3bf7d02cec05093696cec07591ada462271b1d1519eedde0df37a330fe8c22ebd77705917b7e32
+ ae88f45a34a8ba
+ 3037235e19a394be4d26ce47317d8087684456
+ b4cfc5555e925e3e7b2ebc829b2d0505ea617b0ca9531bcdb96040d390
+ 57f5a0f8d6415a8a621157e06114338900a5cd0837278b2751fc96da0d
+ 5e3bc104eafa8f9c;
+ 40e632d562643ccb64286303040fcaf679e914eaddc05af8843ce6a427b99a5dc266de31c09165
+ ""
+ ""
+ ""
+ ""
+ 7810963d0383460c;
+ 237eeefe4b58cc034b9f099f04678c2a9da898b39324cd3087a651014f6796f9c4881d89e127e6
+ 22
+ ""
+ ""
+ ""
+ 914c0d07b56a620c;
+ 21e47e57badd678d490c2f320ff8fb1c42761bd439f3e96dc0ed1d5b2169912af1a4e2c533c52b
+ ""
+ a3
+ ""
+ ""
+ 841a2c9697997e1f;
+ e8c71c23a089e231480aa63c484fb34bd522397f102cb8ecf4f64e329884fe73be257a753b3820
+ ""
+ ""
+ 0b
+ 05
+ 8137867eb2cf4281;
+ c23f94a079bde2dd98d813655dafa15b85419d15c41a5153cce5d0e8c8702db2ba11927589678d
+ 4f7b8fcfad4818c4
+ 11f15f452300903874f9a532ee46496ae753a2340af7b91f
+ 9632fc5ae71ae18b40de751ab6b6761ca16434a9935e466e
+ 38b42c255ef96643eb10b3bc9f2691c2e99fce686f1f475b
+ c32a64eb29ba1822;
+ 11c1cb072f32a59c313dba3db646ae909a096697d9a7b0556463ff1126ebc43263391424d02739
+ d0787e80
+ 4d8f1dccf6c897a8a48431
+ 324324041b5302ccd501b538bd03d5cb5c90d1fd3f7d2be187a787032c79ed9007
+ 181bd0dc71010e424ebc9ef3076822ee1f476f71597408a6bed166e9d1041c5144
+ 4752f2416b0d0b58;
+ 64ee4ce1d3fc042c084f7d8c0c48ad7d6f1eabd0fd1ec24a88f26734d5c8d92dbd873a8fe11309
+ 0d401bea4d28ff
+ 49f10ff593adc258e091abd31b62dd1735158f
+ 98765970acc6602da063aae01a2a199d3a4f37a5f062d216d2053a83b5
+ 80090c15eefaee5a89856fb9a6e0d3754984998915327ea69facb3c3e5
+ 67af4d834f3cdf11;
+ d3a0488ab0d2df631b2892cdfcf9fdd0f37de9ed67179aeae82fe00009428b297b553230a6d917fa0c1a233c9ebc8a4cba45b20543c540fc1b9dbce078b87a1534acf03897b95a3f372e9f6c5a
+ ""
+ ""
+ ""
+ ""
+ 2f94915a82b486df;
+ 5f2ae44a7dbce9ba43a39089de20de70d0544b5151db0a16e9769e8f2fc12c7f839fab269a0056284a697ffd4113a1cf43b5d5bdce2d86dead83f5a356e9106bedf908db61f1119f9700260ea9
+ 37
+ ""
+ ""
+ ""
+ f02d5d46eab2e377;
+ 9cc7232184d217158fee8ca42e75614739e9007f234fbcd86b0ad8f641a0449b6d9b0f99d1cb4a57a4d6f987feb0ade90aa1d81c4f497b3734be301da3e25fe692629db57311f422f3a1573f9e
+ ""
+ 05
+ ""
+ ""
+ e3c6faf9bbec6f8a;
+ 53a23e96265e4326fa532d7136863e5b4bc6c99ade3d4eb23cacdf6e42ad8ca13187eba1532920ba31582b3793b05fa65e9f80c5814b91f4d3c581c7b16c46b484859c6d19eebaf124681aa3be
+ ""
+ ""
+ 99
+ 50
+ 8e188c981fa9757d;
+ 43307fa4ef095ef8e7e50b703dc0420e74227c9351366ef8e98e1e24b48aa989dbb8d0f10471ae5428a6012fbe4f5cb2dab2863e574842cc0b3774e00dcfa63b0db1716c7e916a26fc2e198f8d
+ b63ab59955989497
+ 782f16c5816270ef3fbe4ea22f484ddc12ec8f4bdbd6ebdf
+ bafb21fcf5427dbee5f95b53a0b4cb6d7c128b79f4657895
+ 4a73ab00c6b33f577e36b151435331661e7a4f8ad2cf2424
+ 3feaf9765a80ad6d;
+ f4b0ba518dd61436140f20d40224baac3a602da83cb254a7e03f052c63c1f3f00f301cc944a1789133bb8048f07dc123f2ca7e20c83988e4bfea6d561ab5aea542db544a14376d5d52f7265c7a
+ 8d2fc4fe
+ ef99b9dba89eb472f71d8e
+ b5affe900d776e4cf74e52b6c86db981143082735c6473a86a5da3d2e8cbb8602e
+ f41bd01dcd02e66f0d3b4771c32053d11c302c6144fb40397bf548b21d6b748655
+ c0c9b188065fbe55;
+ bbaf08bf9315fba15f46714bfd2c8312fb5744dfe84615ddb93f15360161f2efb1fc39b8b6ad97427dcaa0435bee7f3a5c11fd01b9c120aa6004f84bcba838a1c33beb4087719135b355dce9ff
+ d6fd639f192e4c
+ 2c9a2752bf74a3f63408d3b27df51f44ed5537
+ bfb0162f05edbad1b2c36ceec1dc407475b8e05fcb5ee66c7205f21804
+ 7a28b08624230f3c25eac43abc77e6525efd4ccf45b72033af74c47021
+ 70cf57e5e7d02c97;
+}
+
+rc5-ocb1 {
+ 60d7bcda163547d348b7551195e77022907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268eeee533285a6ed810c9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057
+ acc87638f5080467
+ ""
+ ""
+ ""
+ aa54e91505bc3ec6;
+ 33d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f8f28523c03d4de
+ 1600157846b710ee
+ 72
+ ""
+ ""
+ 5e23eb9cc063fb52;
+ 807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c46f
+ 88de9fd41e72d7b9
+ ""
+ 7e
+ 14
+ 8086d6e7472314d3;
+ 23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a874498
+ ad0abef8bc4fcb70
+ ""
+ e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0
+ ace115dc9234795ceda92323b7555d9b7088d5f03851f5a8
+ ad07550f521cb01d;
+ c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003
+ cc0cae9ce021a5f1
+ fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18c
+ bfe6effd1ff6778554acf1270485b203a3c1c4c967c0a458
+ 9ef4ec1d3bd29e3da733811d8d32183a38e0c77c4fa209f4
+ e2244052d820e90f;
+ cb948bdd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a5718fd25014107c8e7d715a92add9589d1f5c054b2
+ d983514605ec5902
+ ""
+ 94a319b9802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70d17d
+ 568ebf6a8b3c3aa4bb11dfe4794a9b2dce157fc51ea99119a0b680fba6
+ a7720c81e5980c76;
+ 4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4563d405e51881e99027b8ab9aea3ccf860b0009740763d96836c5f87b95460938de1288c69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c36800d96
+ 45563a308ba60076
+ 817523bd2abf1261b089d8f23a9c2835076a23
+ faac2cdd67771cc667a8331f0a170b66283e4f834a06148f302c3973ac
+ b3118f057e88cb0db02cdb8fac8f78723937c596e56beeda7f56cc4098
+ 90496eb2b1214b4c;
+ cd56f6f24e33958b8c2e2352fd61e4fa8fec816ac861a8b33779f09e7a10fc02a8f48afa3080ee119a52a9a817e4f2b94b0820cab383a8cffeea7c486315799dc875fba578c8ec4837898a92142b5b0677da1ac273117b45bcfff5d5f8b6fde2893232a9f81d14517ffae475f6b94a43a67b3d380d2f9aaafe2dd721c0095c8808847689211450ba8095ffab1eaadf66fd22ac1976063e113ab61f813e28a1397a7974a1d7f4220c785fe426a5a0e80f678d404147842941feeffdc2eb44dc8c0d5e8f444f7f4e0c893959b74dc23a7bb40e7e0013e5150686d2301b43
+ a15a84e81d7f5ced
+ ""
+ ""
+ ""
+ c80dc735b4b0d91c;
+ aa49e2414ebf47970e560475cff206877de69146acc3ab6cf8556b7aa776945948d1b8834df2196c92ec1718dcdeee0d52d9539726d2810391b3f9d10c39b07ae8f08ce7cee4758a386a9943e97dedfbe61e737882cd09c2b9a80f34c0fde11c2481b11fc76bfa4dbf710a9e544e0c536ca1e040f9ad5b04140d98edabe08485290a4d87d13b07398a1458c2c6b61dbdbc1cccada8c1a0a9aabb6c4e3c3554f8fb1ef61614c270295dfc0ca6551ca4bdb75359f91cb9d921056b7de74fc9a9b37154ce6c0b396179d31f06a1dd5982cbc0d7cb23841da1ae8f4ae480cd
+ a98ad6cf2bacf6f9
+ fd
+ ""
+ ""
+ e90954047fa57813;
+ 3f821330c43f3df6c2b3fac7cbcf96523d4723f91801325eb8553236651c96788d73d192ee53b3f3ebd66ddd98cedbe88e245de25b1593b70f8601562d90a9b59ed034a867642d25d54756fa5c47f16f64b837bb4926214211a1c696ba172010abb433922a22d9fd881519165eb9d85197a21cc34ac0d5ae7be8dbf98e4ffed2cf6b1372a5aa47b54fd9d70c70e117bf1cae71b3a56f0e7d839ea59cc783443d64f2ed6a29b96856beca34fd6544bcf86b799e2a1681160ccf055f0fd3001da597a1406d465b7b1419ea51cf858f938f6daafbd656445a09898eaa96ff
+ c3d1d2e31e4e34c9
+ ""
+ 4b
+ b5
+ baf615ac4d6842ea;
+ 8bfae64825ecd75a66d88eedb969ffe07669845ebb7a24c69f13d099f47166edf54538e88fbf433a7ff212085179e79771f6eee7283ab178ef2b800d7b969da05780ffc1ba78c70dda7a4ca2a25e771702fb1901ecfc8a959cb8e75079bb018ccc8c54f31b450e88f8e9002926ad0284c738f4cb0f58a1e34c8b15ad930c1b627235a2cb84241986c251f5b70be2367f047265264e0da72efe8995e6c932a17eab511eddb8e4ba463c663035a6ae8a7a899e4279d54d03f0e0f3e961dcfd40088d5be74088e4097efb0368c7e2f431ee6988cf2a0e9ebeb3de79c4f86c
+ 9e4fba61339d6d90
+ ""
+ 7eab7707ca48ff5ba1ae93d16225d469de5747bc1addf574
+ 757d492944cb37a370da05afd0734e35c6bc4a0f970843ed
+ 33e2b21461d5dd3d;
+ 8729720a320fe14fd29cfc59314fe2079c0a2535ded56112d6e3d33dcf7c71cd7d130323794e3da84a9df69703a9caf02d2a8f57ac71e554a6850d55882f8c7ae6994fc8528bd18c374fc43581d2f72a89584a2404a059f7f99c7241a0c879d6d4455b382a9ce757b3e7a1d07585ad9d7ea9c7c9cf54f3bc6d94238ab56d738e02abd651477cd726d6f3ebcd6fadeab50906642a7de6496247060e7be3632ed9bd94bb42f45a8733b2cd2df9d1d905cfdb29983050d6bcdb686a0c897031ad09a5b8fa687ec3bad8e18dc2ad361f1e226e78876cd35f86c639733c5cd8
+ 4aed8aaebabb7e0f
+ 24edfd9710b7bca91b612ea37fc5cc09f7f62f66b423fcd2
+ dec5de24d264f2c839839c1b06319f687dbc68d9f07fd41c
+ aefcbff3659b393a7cf6952eb2fd4ad464d1be5c0c13b79b
+ 1ba057a604a1b599;
+ cb4f8cde8de201ec2680332bbded4883deea0b58b54bdd13c17ef292b0ded3caeb5e57fd21df10bc6186265ee6ea45907de6cb822fb2ef953aea358a03e0fce2e1b9511bd332c86e67f123377a8f0256b8dcc73ae1b3c6cd3f104e3cb24284cfed17811d64d492d39ea7496993a25b072945d83f923e66b0a6689cf0969c003a8fca80e322a4b1bf050c1220450433efb6b6d8a2d820cf27a64b9d47f636845dac557bb3e75f3a18fb8e173416867fcd0ee78ddd9236beec76d55ed58b10f91d07a037791ab96e83c4bf2fb5b205e592c172a5cbc19456c95c1bea6079
+ f3867e52d663cb38
+ ""
+ 84b2a0a8ff825df752423f3179bfeb89eca385f20ddce5f1f23564672e
+ 19b818cf69f0e92cd5a9f539f91e73dc543141acde903d98a24e1234c8
+ a41bbb9bbe7c82db;
+ 370ffc37d400a31e8aac1d426ce10df73c5ee478b3b63d91024780e974a8a2a0e7a36f84ab1286b627e7d01b38a84a6de738721ed80fd0d7f69fa658abb5a440d304128719b541a9451cead18e4c61d93d1f8fcc53574427767396322b3bf7d02cec05093696cec07591ada462271b1d1519eedde0df37a330fe8c22ebd77705917b7e32ae88f45a34a8ba3037235e19a394be4d26ce47317d8087684456b4cfc5555e925e3e7b2ebc829b2d0505ea617b0ca9531bcdb96040d39040e632d562643ccb64286303040fcaf679e914eaddc05af8843ce6a427b99a5dc266
+ de31c09165237eee
+ fe4b58cc034b9f099f04678c2a9da898b39324
+ cd3087a651014f6796f9c4881d89e127e62221e47e57badd678d490c2f
+ f2bc32f9e6d98d55aa5631671de574e5b6e0e0e17a59f20f418d3555f8
+ 6a92cb246769b913;
+ 320ff8fb1c42761bd439f3e96dc0ed1d5b2169912af1a4e2c533c52ba3e8c71c23a089e231480a
+ a63c484fb34bd522
+ ""
+ ""
+ ""
+ 6dcc9a87c6b58479;
+ 397f102cb8ecf4f64e329884fe73be257a753b38200bc23f94a079bde2dd98d813655dafa15b85
+ 419d15c41a5153cc
+ e5
+ ""
+ ""
+ 62692c7d1e45c739;
+ d0e8c8702db2ba11927589678d4f7b8fcfad4818c411f15f452300903874f9a532ee46496ae753
+ a2340af7b91f9632
+ ""
+ fc
+ e3
+ bd2bbcb67cb7a71b;
+ 5ae71ae18b40de751ab6b6761ca16434a9935e466e11c1cb072f32a59c313dba3db646ae909a09
+ 6697d9a7b0556463
+ ""
+ ff1126ebc43263391424d02739d0787e804d8f1dccf6c897
+ 4a7b3da4e48db3ad461bce3fa4e1eb8bfe3d5415b80884f8
+ e8e7fdcdb5bd4809;
+ a8a48431324324041b5302ccd501b538bd03d5cb5c90d1fd3f7d2be187a787032c79ed900764ee
+ 4ce1d3fc042c084f
+ 7d8c0c48ad7d6f1eabd0fd1ec24a88f26734d5c8d92dbd87
+ 3a8fe113090d401bea4d28ff49f10ff593adc258e091abd3
+ 7f77bf26d0ccc5527ce3a51a3802d09ea7817507df9dbaeb
+ 64cd828bd8c60820;
+ 1b62dd1735158f98765970acc6602da063aae01a2a199d3a4f37a5f062d216d2053a83b5d3a048
+ 8ab0d2df631b2892
+ ""
+ cdfcf9fdd0f37de9ed67179aeae82fe00009428b297b553230a6d917fa
+ 220fc76c73b6b558f327d88b2ceb3c28b23e09ab5b15757d041a66548f
+ 99c4bfbe566dbede;
+ 0c1a233c9ebc8a4cba45b20543c540fc1b9dbce078b87a1534acf03897b95a3f372e9f6c5a5f2a
+ e44a7dbce9ba43a3
+ 9089de20de70d0544b5151db0a16e9769e8f2f
+ c12c7f839fab269a0056284a697ffd4113a1cf43b5d5bdce2d86dead83
+ 129f452d3b69b5c33ce6507970c4f36352a7c4bf4e3d621185fa8ef09a
+ c7267b667c9d44bd;
+ f5a356e9106bedf908db61f1119f9700260ea9379cc7232184d217158fee8ca42e75614739e9007f234fbcd86b0ad8f641a0449b6d9b0f99d1cb4a57a4d6f987feb0ade90aa1d81c4f497b3734
+ be301da3e25fe692
+ ""
+ ""
+ ""
+ d59834fe604f12e2;
+ 629db57311f422f3a1573f9e0553a23e96265e4326fa532d7136863e5b4bc6c99ade3d4eb23cacdf6e42ad8ca13187eba1532920ba31582b3793b05fa65e9f80c5814b91f4d3c581c7b16c46b4
+ 84859c6d19eebaf1
+ 24
+ ""
+ ""
+ 0c9a3b106bc9bca6;
+ 681aa3be9943307fa4ef095ef8e7e50b703dc0420e74227c9351366ef8e98e1e24b48aa989dbb8d0f10471ae5428a6012fbe4f5cb2dab2863e574842cc0b3774e00dcfa63b0db1716c7e916a26
+ fc2e198f8db63ab5
+ ""
+ 99
+ 87
+ 2b28f9babe659513;
+ 55989497782f16c5816270ef3fbe4ea22f484ddc12ec8f4bdbd6ebdfbafb21fcf5427dbee5f95b53a0b4cb6d7c128b79f4657895f4b0ba518dd61436140f20d40224baac3a602da83cb254a7e0
+ 3f052c63c1f3f00f
+ ""
+ 301cc944a1789133bb8048f07dc123f2ca7e20c83988e4bf
+ 8be72ebd52cb194d6b0e4fc423bb898f655d938d11985432
+ 0564db4049183242;
+ ea6d561ab5aea542db544a14376d5d52f7265c7a8d2fc4feef99b9dba89eb472f71d8eb5affe900d776e4cf74e52b6c86db981143082735c6473a86a5da3d2e8cbb8602ebbaf08bf9315fba15f
+ 46714bfd2c8312fb
+ 5744dfe84615ddb93f15360161f2efb1fc39b8b6ad97427d
+ caa0435bee7f3a5c11fd01b9c120aa6004f84bcba838a1c3
+ 49ac4c21db7bcf9453e935aadb85d304afe6fa4bb10002a0
+ 9a90ed7bab6f9d86;
+ 3beb4087719135b355dce9ffd6fd639f192e4c2c9a2752bf74a3f63408d3b27df51f44ed5537bfb0162f05edbad1b2c36ceec1dc407475b8e05fcb5ee66c7205f21804c3b73451dc9a3aed7667
+ c6342c8355ff66b9
+ ""
+ 1eeffa115cf118eef301f2c93fda303878f7987116dba62d93a7da7027
+ a3c938b621c4032adbd7b5bfeedff1eaa471ddefb2f396290902c00d59
+ d682d2ff660fa862;
+ 4ffe5a6506e4e1439de76cc9d332ab03510df3c7d35dc526b5b7785400f53d34b5d55fcac5fbeadd81456bbe6bcedb015be40bfbda656483b32fc4d0a9dc2d7a68b134919d79de5268d7d2ce37
+ 2a8a386aa718d09e
+ 19612f3d10fe569863bbd3ad42903905058b93
+ 4eb213aa037de4e26cd4ceff7490353b5e7621d67ee3ddfb2584e1e12d
+ c494267b5ee0e2bd32b3c4e93b70ddfef6985a4d8360ed32e45209192f
+ 32e85181b5d1d655;
+}
+
+rc5-pmac1 {
+ 60d7bcda163547d348b7551195e77022907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268eeee533285a6ed810c9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057
+ ""
+ 25f3e24d8ae10215;
+ acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26afa3349829b94586306fed5415
+ 4f
+ f7da3d0334f4ad55;
+ 8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a
+ 96ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b9
+ 5d24a4c29b90fa71;
+ 7e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a8744
+ 98ad0abef8bc4fcb70e27e98ef1f0446b42fb1
+ ca50a7dd104238aa;
+ 44d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff677
+ ""
+ dfde25eb32b74a23;
+ 8554acf1270485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a5718fd25014107c8e7d715a92add9589d1f5c054b2d983514605ec590294a319b9802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70d1
+ 7d
+ 58afcfd1b2ec5cca;
+ 4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4563d405e51881e99027b8ab9aea3ccf860b0009740763d96836c5f87b95460938de1288c69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c36800d9645563a308ba60076817523bd2abf1261b089d8f23a9c2835076a23faac2cdd67771cc667a8331f0a170b66283e4f834a06148f302c
+ 3973accd56f6f24e33958b8c2e2352fd61e4fa8fec816ac8
+ 3a50ecc246becae2;
+ 61a8b33779f09e7a10fc02a8f48afa3080ee119a52a9a817e4f2b94b0820cab383a8cffeea7c486315799dc875fba578c8ec4837898a92142b5b0677da1ac273117b45bcfff5d5f8b6fde2893232a9f81d14517ffae475f6b94a43a67b3d380d2f9aaafe2dd721c0095c8808847689211450ba8095ffab1eaadf66fd22ac1976063e113ab61f813e28a1397a7974a1d7f4220c785fe426a5a0e80f678d404147842941feeffdc2eb44dc8c0d5e8f444f7f4e0c893959b74dc23a7bb40e7e0013e5150686d2301b43a15a84e81d7f5cedaa49e2414ebf47970e560475cf
+ f206877de69146acc3ab6cf8556b7aa7769459
+ ce6c1f810be61bf6;
+ 48d1b8834df2196c92ec1718dcdeee0d52d9539726d2810391b3f9d10c39b07ae8f08ce7cee475
+ ""
+ 497b2f55a33bed03;
+ 8a386a9943e97dedfbe61e737882cd09c2b9a80f34c0fde11c2481b11fc76bfa4dbf710a9e544e
+ 0c
+ 616706b07020fd1b;
+ 536ca1e040f9ad5b04140d98edabe08485290a4d87d13b07398a1458c2c6b61dbdbc1cccada8c1
+ a0a9aabb6c4e3c3554f8fb1ef61614c270295dfc0ca6551c
+ af712aca3c532277;
+ a4bdb75359f91cb9d921056b7de74fc9a9b37154ce6c0b396179d31f06a1dd5982cbc0d7cb2384
+ 1da1ae8f4ae480cda98ad6cf2bacf6f9fd3f82
+ d47974ebfc5228ef;
+ 1330c43f3df6c2b3fac7cbcf96523d4723f91801325eb8553236651c96788d73d192ee53b3f3ebd66ddd98cedbe88e245de25b1593b70f8601562d90a9b59ed034a867642d25d54756fa5c47f1
+ ""
+ ee84e75847026484;
+ 6f64b837bb4926214211a1c696ba172010abb433922a22d9fd881519165eb9d85197a21cc34ac0d5ae7be8dbf98e4ffed2cf6b1372a5aa47b54fd9d70c70e117bf1cae71b3a56f0e7d839ea59c
+ c7
+ 5605efcbb6e07489;
+ 83443d64f2ed6a29b96856beca34fd6544bcf86b799e2a1681160ccf055f0fd3001da597a1406d465b7b1419ea51cf858f938f6daafbd656445a09898eaa96ffc3d1d2e31e4e34c94b8bfae648
+ 25ecd75a66d88eedb969ffe07669845ebb7a24c69f13d099
+ 6182d51653af224a;
+ f47166edf54538e88fbf433a7ff212085179e79771f6eee7283ab178ef2b800d7b969da05780ffc1ba78c70dda7a4ca2a25e771702fb1901ecfc8a959cb8e75079bb018ccc8c54f31b450e88f8
+ e9002926ad0284c738f4cb0f58a1e34c8b15ad
+ 27da50a416aca31c;
+}
+
+rc5-ocb3 {
+ 60d7bcda163547d348b7551195e77022907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268eeee533285a6ed810c9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057
+ acc87638f508
+ ""
+ ""
+ ""
+ 063c1bf330553d8c;
+ 046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f8f28523c03
+ d4de16001578
+ 46
+ ""
+ ""
+ b6a770d618bfc1d7;
+ b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09
+ c063c46f88de
+ ""
+ 9f
+ 74
+ 570a5073b8afc17f;
+ d41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca9
+ 86981a
+ ""
+ 874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b
+ fa80154a33c295155643798240fd22d30613b2b6770a3327
+ 31aca92d9606f720;
+ 6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc
+ 69f6a9f2c0
+ 945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a125
+ 8b2b9b8f0911e32d65cc1770a18cbfe6effd1ff6778554ac
+ afeb6335d22d91e6027e219981fa6d22fa23d4170ee22c35
+ 09e60a6bdcc1ba7f;
+ f1270485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a5718fd25014107
+ c8e7d715a92a
+ ""
+ dd9589d1f5c054b2d983514605ec590294a319b9802068a9f891bc5ba5
+ f29328c6d4104e0e1ef80cd7494957aad54f69ae2d1b95e1421c03f769
+ 7d433a869031bf7e;
+ afabf8c3122d12d7ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4563d405e51881e99027b8ab9aea3ccf860b0009740763d96836c5f87b95460938de1288c69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7a3aa7e740d
+ a967828e3604
+ b35b15ffaa6c36800d9645563a308ba6007681
+ 7523bd2abf1261b089d8f23a9c2835076a23faac2cdd67771cc667a833
+ d403996de8929a47a908bee11ffacc01a85f3d7af8c78ec0094a83e2ea
+ 10a662f856acdb4a;
+ 1f0a170b66283e4f834a06148f302c3973accd56f6f24e33958b8c2e2352fd61e4fa8fec816ac861a8b33779f09e7a10fc02a8f48afa3080ee119a52a9a817e4f2b94b0820cab383a8cffeea7c486315799dc875fba578c8ec4837898a92142b5b0677da1ac273117b45bcfff5d5f8b6fde2893232a9f81d14517ffae475f6b94a43a67b3d380d2f9aaafe2dd721c0095c8808847689211450ba8095ffab1eaadf66fd22ac1976063e113ab61f813e28a1397a7974a1d7f4220c785fe426a5a0e80f678d404147842941feeffdc2eb44dc8c0d5e8f444f7f4e0c893959
+ b74dc23a7bb4
+ ""
+ ""
+ ""
+ 4fa9e8d71758235e;
+ 0e7e0013e5150686d2301b43a15a84e81d7f5cedaa49e2414ebf47970e560475cff206877de69146acc3ab6cf8556b7aa776945948d1b8834df2196c92ec1718dcdeee0d52d9539726d2810391b3f9d10c39b07ae8f08ce7cee4758a386a9943e97dedfbe61e737882cd09c2b9a80f34c0fde11c2481b11fc76bfa4dbf710a9e544e0c536ca1e040f9ad5b04140d98edabe08485290a4d87d13b07398a1458c2c6b61dbdbc1cccada8c1a0a9aabb6c4e3c3554f8fb1ef61614c270295dfc0ca6551ca4bdb75359f91cb9d921056b7de74fc9a9b37154ce6c0b396179d3
+ 1f06a1dd5982
+ cb
+ ""
+ ""
+ bba7bb90cb237373;
+ c0d7cb23841da1ae8f4ae480cda98ad6cf2bacf6f9fd3f821330c43f3df6c2b3fac7cbcf96523d4723f91801325eb8553236651c96788d73d192ee53b3f3ebd66ddd98cedbe88e245de25b1593b70f8601562d90a9b59ed034a867642d25d54756fa5c47f16f64b837bb4926214211a1c696ba172010abb433922a22d9fd881519165eb9d85197a21cc34ac0d5ae7be8dbf98e4ffed2cf6b1372a5aa47b54fd9d70c70e117bf1cae71b3a56f0e7d839ea59cc783443d64f2ed6a29b96856beca34fd6544bcf86b799e2a1681160ccf055f0fd3001da597a1406d465b7b
+ 1419ea51cf85
+ ""
+ 8f
+ fe
+ e5476d3424c2d40f;
+ 938f6daafbd656445a09898eaa96ffc3d1d2e31e4e34c94b8bfae64825ecd75a66d88eedb969ffe07669845ebb7a24c69f13d099f47166edf54538e88fbf433a7ff212085179e79771f6eee7283ab178ef2b800d7b969da05780ffc1ba78c70dda7a4ca2a25e771702fb1901ecfc8a959cb8e75079bb018ccc8c54f31b450e88f8e9002926ad0284c738f4cb0f58a1e34c8b15ad930c1b627235a2cb84241986c251f5b70be2367f047265264e0da72efe8995e6c932a17eab511eddb8e4ba463c663035a6ae8a7a899e4279d54d03f0e0f3e961dcfd40088d5be74088
+ e4097e
+ ""
+ fb0368c7e2f431ee6988cf2a0e9ebeb3de79c4f86c9e4fba
+ 828b48b63905d7d298cf4f88d099cc209fe7483985517503
+ 6bd18f02c7a6c90e;
+ 61339d6d907eab7707ca48ff5ba1ae93d16225d469de5747bc1addf5748729720a320fe14fd29cfc59314fe2079c0a2535ded56112d6e3d33dcf7c71cd7d130323794e3da84a9df69703a9caf02d2a8f57ac71e554a6850d55882f8c7ae6994fc8528bd18c374fc43581d2f72a89584a2404a059f7f99c7241a0c879d6d4455b382a9ce757b3e7a1d07585ad9d7ea9c7c9cf54f3bc6d94238ab56d738e02abd651477cd726d6f3ebcd6fadeab50906642a7de6496247060e7be3632ed9bd94bb42f45a8733b2cd2df9d1d905cfdb29983050d6bcdb686a0c897031ad09
+ a5b8fa687e
+ c3bad8e18dc2ad361f1e226e78876cd35f86c639733c5cd8
+ 4aed8aaebabb7e0f24edfd9710b7bca91b612ea37fc5cc09
+ 0089fb21527fed153e81acdc9229d8341ca36df6ebdada9b
+ cc5b59ffe07eaff8;
+ f7f62f66b423fcd2dec5de24d264f2c839839c1b06319f687dbc68d9f07fd41ccb4f8cde8de201ec2680332bbded4883deea0b58b54bdd13c17ef292b0ded3caeb5e57fd21df10bc6186265ee6ea45907de6cb822fb2ef953aea358a03e0fce2e1b9511bd332c86e67f123377a8f0256b8dcc73ae1b3c6cd3f104e3cb24284cfed17811d64d492d39ea7496993a25b072945d83f923e66b0a6689cf0969c003a8fca80e322a4b1bf050c1220450433efb6b6d8a2d820cf27a64b9d47f636845dac557bb3e75f3a18fb8e173416867fcd0ee78ddd9236beec76d55ed58b
+ 10f91d07a037
+ ""
+ 791ab96e83c4bf2fb5b205e592c172a5cbc19456c95c1bea6079f3867e
+ 0853cf3d4515b9e4b005c95fdddf3c74d4d3ccdaaa1015ae379b550302
+ 2a56e4bba5f8d187;
+ 52d663cb3884b2a0a8ff825df752423f3179bfeb89eca385f20ddce5f1f23564672e370ffc37d400a31e8aac1d426ce10df73c5ee478b3b63d91024780e974a8a2a0e7a36f84ab1286b627e7d01b38a84a6de738721ed80fd0d7f69fa658abb5a440d304128719b541a9451cead18e4c61d93d1f8fcc53574427767396322b3bf7d02cec05093696cec07591ada462271b1d1519eedde0df37a330fe8c22ebd77705917b7e32ae88f45a34a8ba3037235e19a394be4d26ce47317d8087684456b4cfc5555e925e3e7b2ebc829b2d0505ea617b0ca9531bcdb96040d390
+ 40e632d56264
+ 3ccb64286303040fcaf679e914eaddc05af884
+ 3ce6a427b99a5dc266de31c09165237eeefe4b58cc034b9f099f04678c
+ 48d32eec290f067c12f81697153f4030c56b1b79ffe695bc972ffda584
+ 15d05287d12f9c8f;
+ 2a9da898b39324cd3087a651014f6796f9c4881d89e127e62221e47e57badd678d490c2f320ff8
+ fb1c42761bd4
+ ""
+ ""
+ ""
+ 19796de26b769f5b;
+ 39f3e96dc0ed1d5b2169912af1a4e2c533c52ba3e8c71c23a089e231480aa63c484fb34bd52239
+ 7f102cb8ecf4
+ f6
+ ""
+ ""
+ 22f17895a971f1f3;
+ 4e329884fe73be257a753b38200bc23f94a079bde2dd98d813655dafa15b85419d15c41a5153cc
+ e5d0e8c8702d
+ ""
+ b2
+ 6f
+ 511d62bc5b29da6c;
+ ba11927589678d4f7b8fcfad4818c411f15f452300903874f9a532ee46496ae753a2340af7b91f
+ 9632fc
+ ""
+ 5ae71ae18b40de751ab6b6761ca16434a9935e466e11c1cb
+ a60bb59c8292e00486962cb216e756dd66613fe9569e549d
+ ed2836258e0dfe45;
+ 072f32a59c313dba3db646ae909a096697d9a7b0556463ff1126ebc43263391424d02739d0787e
+ 804d8f1dcc
+ f6c897a8a48431324324041b5302ccd501b538bd03d5cb5c
+ 90d1fd3f7d2be187a787032c79ed900764ee4ce1d3fc042c
+ 84e43f8b78a4b759d7832084f4a43b94380155ead68222cf
+ 53e98d05afc28fb5;
+ 084f7d8c0c48ad7d6f1eabd0fd1ec24a88f26734d5c8d92dbd873a8fe113090d401bea4d28ff49
+ f10ff593adc2
+ ""
+ 58e091abd31b62dd1735158f98765970acc6602da063aae01a2a199d3a
+ ccad9333e858aba3b6be61d2821fc6485b94dee4fd3da0f24e18c5c8eb
+ befad9a49693a9ff;
+ 4f37a5f062d216d2053a83b5d3a0488ab0d2df631b2892cdfcf9fdd0f37de9ed67179aeae82fe0
+ 0009428b297b
+ 553230a6d917fa0c1a233c9ebc8a4cba45b205
+ 43c540fc1b9dbce078b87a1534acf03897b95a3f372e9f6c5a5f2ae44a
+ d4841df4923358d24721e29a4395fd8410f672286fb862f234d7afe446
+ fbca241edc3784af;
+ 7dbce9ba43a39089de20de70d0544b5151db0a16e9769e8f2fc12c7f839fab269a0056284a697ffd4113a1cf43b5d5bdce2d86dead83f5a356e9106bedf908db61f1119f9700260ea9379cc723
+ 2184d217158f
+ ""
+ ""
+ ""
+ a8dca51e818d1620;
+ ee8ca42e75614739e9007f234fbcd86b0ad8f641a0449b6d9b0f99d1cb4a57a4d6f987feb0ade90aa1d81c4f497b3734be301da3e25fe692629db57311f422f3a1573f9e0553a23e96265e4326
+ fa532d713686
+ 3e
+ ""
+ ""
+ 22724c59a99e8a28;
+ 5b4bc6c99ade3d4eb23cacdf6e42ad8ca13187eba1532920ba31582b3793b05fa65e9f80c5814b91f4d3c581c7b16c46b484859c6d19eebaf124681aa3be9943307fa4ef095ef8e7e50b703dc0
+ 420e74227c93
+ ""
+ 51
+ cd
+ d31ba86abcc74ed5;
+ 366ef8e98e1e24b48aa989dbb8d0f10471ae5428a6012fbe4f5cb2dab2863e574842cc0b3774e00dcfa63b0db1716c7e916a26fc2e198f8db63ab59955989497782f16c5816270ef3fbe4ea22f
+ 484ddc
+ ""
+ 12ec8f4bdbd6ebdfbafb21fcf5427dbee5f95b53a0b4cb6d
+ 377776c7a23f367f4b797164000341b828e9af1528512d7e
+ 640622b80de68169;
+ 7c128b79f4657895f4b0ba518dd61436140f20d40224baac3a602da83cb254a7e03f052c63c1f3f00f301cc944a1789133bb8048f07dc123f2ca7e20c83988e4bfea6d561ab5aea542db544a14
+ 376d5d52f7
+ 265c7a8d2fc4feef99b9dba89eb472f71d8eb5affe900d77
+ 6e4cf74e52b6c86db981143082735c6473a86a5da3d2e8cb
+ 96695b552838f18f1d0cdede1c6e8b7a94686a80d3faafb2
+ 1b2ffe9cea3bdd6f;
+ b8602ebbaf08bf9315fba15f46714bfd2c8312fb5744dfe84615ddb93f15360161f2efb1fc39b8b6ad97427dcaa0435bee7f3a5c11fd01b9c120aa6004f84bcba838a1c33beb4087719135b355
+ dce9ffd6fd63
+ ""
+ 9f192e4c2c9a2752bf74a3f63408d3b27df51f44ed5537bfb0162f05ed
+ 15dacd515d731592ab85c1b5d9f3dbcde30179b31c493a15f6af916588
+ 99a03f7a639d9ac1;
+ bad1b2c36ceec1dc407475b8e05fcb5ee66c7205f21804c3b73451dc9a3aed7667c6342c8355ff66b91eeffa115cf118eef301f2c93fda303878f7987116dba62d93a7da70274ffe5a6506e4e1
+ 439de76cc9d3
+ 32ab03510df3c7d35dc526b5b7785400f53d34
+ b5d55fcac5fbeadd81456bbe6bcedb015be40bfbda656483b32fc4d0a9
+ 82df9af04d4792ef8a746a950613ca561e9d1e395b28cd4efb20400d03
+ b866935e219f4573;
+}
+
+rc5-ocb3-mct {
+ 56 5d65dacd57c2aa33;
+ 52 03beeb48bcdb2c18;
+ 48 01d2c1abfdcd3689;
+ 44 4fe9063599fc965e;
+ 40 02c7d56243840c7c;
+ 36 b8835ac12d93de0c;
+ 32 c04dd9d0ccbc4df6;
+ 28 7d59856e20a6e739;
+ 24 8a1db814d18c6c97;
+ 20 99060d584b19a39f;
+ 16 722f822efb96b14b;
+ 12 20c08832fef3cccd;
+ 10 3bb20b4bb9ae613f;
+ 8 85f66ee439d96c46;
+ 56 f81750a75668;
+ 52 67fff337eefc;
+ 48 53149ad225e2;
+ 44 6cf6c8f56720;
+ 40 795b55a03080;
+ 36 a2aeb71e7493;
+ 32 4581768fa39c;
+ 28 e03e2ac2d905;
+ 24 f0c24fe14ad1;
+ 20 ba83f3fe63f0;
+ 16 c42c1512c9fe;
+ 12 d1934f3572cd;
+ 10 badab855071f;
+ 8 084797262a89;
+ 56 0c1bc6bd;
+ 52 805a3d32;
+ 48 9252506e;
+ 44 f848c865;
+ 40 f4a16d1d;
+ 36 57b79a09;
+ 32 e8b16e4b;
+ 28 a6a0961d;
+ 24 04dd92bc;
+ 20 8ca6413a;
+ 16 2b7d2d10;
+ 12 87440aab;
+ 10 3277a842;
+ 8 b84a6c79;
+}
--- /dev/null
+### Local tests for Rijndael.
+
+rijndael-cmac {
+ ## NIST examples.
+
+ 2b7e151628aed2a6abf7158809cf4f3c
+ ""
+ bb1d6929e95937287fa37d129b756746;
+ 2b7e151628aed2a6abf7158809cf4f3c
+ 6bc1bee22e409f96e93d7e117393172a
+ 070a16b46b4d4144f79bdd9dd04a287c;
+ 2b7e151628aed2a6abf7158809cf4f3c
+ 6bc1bee22e409f96e93d7e117393172aae2d8a57
+ 7d85449ea6ea19c823a7bf78837dfade;
+ 2b7e151628aed2a6abf7158809cf4f3c
+ 6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710
+ 51f0bebf7e3b9d92fc49741779363cfe;
+
+ 8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b
+ ""
+ d17ddf46adaacde531cac483de7a9367;
+ 8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b
+ 6bc1bee22e409f96e93d7e117393172a
+ 9e99a7bf31e710900662f65e617c5184;
+ 8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b
+ 6bc1bee22e409f96e93d7e117393172aae2d8a57
+ 3d75c194ed96070444a9fa7ec740ecf8;
+ 8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b
+ 6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710
+ a1d5df0eed790f794d77589659f39a11;
+
+ 603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4
+ ""
+ 028962f61b7bf89efc6b551f4667d983;
+ 603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4
+ 6bc1bee22e409f96e93d7e117393172a
+ 28a7023f452e8f82bd4bf28d8c37c35c;
+ 603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4
+ 6bc1bee22e409f96e93d7e117393172aae2d8a57
+ 156727dc0878944a023c1fe03bad6d93;
+ 603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4
+ 6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710
+ e1992190549f6ed5696a2c056c315410;
+
+ ## Locally generated tests.
+ 60d7bcda163547d348b7551195e77022
+ ""
+ 63f719651118fd4d45cb4feebc3150cb;
+ 907dd1dff7dac5c9941d26d0c6eb14ad
+ 56
+ bc9d9dfba6e312cfe8e6c500a1d805d3;
+ 8f86edd1dc9268eeee533285a6ed810c
+ 9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a877ff77
+ ba66e97ee7b233119abc32fa42be9401;
+ bf79192a5b50ade5d9cd739a3d1f337f
+ 29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21
+ a51011f5c5d190016cf3e9db6fb32fbc;
+ 635c6d62c9269029df3e6057acc87638f5080467
+ ""
+ 9285e3dc234cbd47605641edd2052999;
+ 33d9ff61cdbda3b3e9878731ebfedd4705e505da
+ 14
+ edc6f130780024d1b8b18361790d949c;
+ 35dceaa7b1cc49ae1d50c38201a894476b3f102b
+ 752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3
+ ac7f798e3227ecb5e4d868c6f07ce3d0;
+ a4f3ebbbb18ac6c95a97a48030370c33d090c542
+ 15abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26afa3349829
+ 9045fe42a3307e0d86fa17dbaa73196b;
+ b94586306fed54154f8f28523c03d4de1600157846b710ee72807a22
+ ""
+ b74dbdd96ca8714c2223ce172d7c5541;
+ 19bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d
+ 42
+ bcbf74240e12721322ac24676c8eeb16;
+ f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e
+ 533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5c
+ 1889506d1415435dbc580f7b05c1c2e4;
+ fb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc81517
+ 84873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6
+ ccf79bcc9696a3887f23f791aa3fbafa;
+ eabdff3bcd211499268878db
+ ""
+ 72c93457d9e50f9ce47227ce159722c7;
+ f30f1dad89d4b9b12012e471
+ 3d
+ 63c431d9cc49118b4af79b5dbf2efded;
+ f46795630e7952d22bb02d71
+ 00b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d0798391805da0
+ 86b6a12fb898bf6a4cad2052a70864ad;
+ 8da3aefc5f8584b7c5e61766
+ 9c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb6
+ 3a2d6cd3d65ba29059613d7e6b6e1278;
+}
+
+rijndael-ccm {
+ ## From the Housley, Whiting, and Ferguson submission to NIST, somewhat
+ ## rearranged because of the bizarre (and undocumented) nonce structure.
+
+ c0c1c2c3c4c5c6c7c8c9cacbcccdcecf
+ 00000003020100a0a1a2a3a4a5
+ 0001020304050607
+ 08090a0b0c0d0e0f101112131415161718191a1b1c1d1e
+ 588c979a61c663d2f066d0c2c0f989806d5f6b61dac384
+ 17e8d12cfdf926e0;
+ c0c1c2c3c4c5c6c7c8c9cacbcccdcecf
+ 00000004030201a0a1a2a3a4a5
+ 0001020304050607
+ 08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ 72c91a36e135f8cf291ca894085c87e3cc15c439c9e43a3b
+ a091d56e10400916;
+ c0c1c2c3c4c5c6c7c8c9cacbcccdcecf
+ 00000005040302a0a1a2a3a4a5
+ 0001020304050607
+ 08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
+ 51b1e5f44a197d1da46b0f8e2d282ae871e838bb64da859657
+ 4adaa76fbd9fb0c5;
+ c0c1c2c3c4c5c6c7c8c9cacbcccdcecf
+ 00000006050403a0a1a2a3a4a5
+ 000102030405060708090a0b
+ 0c0d0e0f101112131415161718191a1b1c1d1e
+ a28c6865939a9a79faaa5c4c2a9d4a91cdac8c
+ 96c861b9c9e61ef1;
+ c0c1c2c3c4c5c6c7c8c9cacbcccdcecf
+ 00000007060504a0a1a2a3a4a5
+ 000102030405060708090a0b
+ 0c0d0e0f101112131415161718191a1b1c1d1e1f
+ dcf1fb7b5d9e23fb9d4e131253658ad86ebdca3e
+ 51e83f077d9c2d93;
+ c0c1c2c3c4c5c6c7c8c9cacbcccdcecf
+ 00000008070605a0a1a2a3a4a5
+ 000102030405060708090a0b
+ 0c0d0e0f101112131415161718191a1b1c1d1e1f20
+ 6fc1b011f006568b5171a42d953d469b2570a4bd87
+ 405a0443ac91cb94;
+ c0c1c2c3c4c5c6c7c8c9cacbcccdcecf
+ 00000009080706a0a1a2a3a4a5
+ 0001020304050607
+ 08090a0b0c0d0e0f101112131415161718191a1b1c1d1e
+ 0135d1b2c95f41d5d1d4fec185d166b8094e999dfed96c
+ 048c56602c97acbb7490;
+ c0c1c2c3c4c5c6c7c8c9cacbcccdcecf
+ 0000000a090807a0a1a2a3a4a5
+ 0001020304050607
+ 08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ 7b75399ac0831dd2f0bbd75879a2fd8f6cae6b6cd9b7db24
+ c17b4433f434963f34b4;
+ c0c1c2c3c4c5c6c7c8c9cacbcccdcecf
+ 0000000b0a0908a0a1a2a3a4a5
+ 0001020304050607
+ 08090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20
+ 82531a60cc24945a4b8279181ab5c84df21ce7f9b73f42e197
+ ea9c07e56b5eb17e5f4e;
+ c0c1c2c3c4c5c6c7c8c9cacbcccdcecf
+ 0000000c0b0a09a0a1a2a3a4a5
+ 000102030405060708090a0b
+ 0c0d0e0f101112131415161718191a1b1c1d1e
+ 07342594157785152b074098330abb141b947b
+ 566aa9406b4d999988dd;
+ c0c1c2c3c4c5c6c7c8c9cacbcccdcecf
+ 0000000d0c0b0aa0a1a2a3a4a5
+ 000102030405060708090a0b
+ 0c0d0e0f101112131415161718191a1b1c1d1e1f
+ 676bb20380b0e301e8ab79590a396da78b834934
+ f53aa2e9107a8b6c022c;
+ c0c1c2c3c4c5c6c7c8c9cacbcccdcecf
+ 0000000e0d0c0ba0a1a2a3a4a5
+ 000102030405060708090a0b
+ 0c0d0e0f101112131415161718191a1b1c1d1e1f20
+ c0ffa0d6f05bdb67f24d43a4338d2aa4bed7b20e43
+ cd1aa31662e7ad65d6db;
+ aca23752615c82c1d454c4fc1462dcf3
+ 00b9965d963ec163c54530549a
+ 20f2c84a078983d6
+ d9215a08e37911f08e13e868d561fd8de3bc968e0978ae
+ 8ca7df83589d89f1e2f9633a4e219e4e8c4daf918cbd4a
+ 795fa85da6e5711c;
+ aca23752615c82c1d454c4fc1462dcf3
+ 0044144a825d7363c54530549a
+ 23bc9db76f5e4761
+ 5297b4a9984845b03b01cf4794fa66cf27cc89c002ff4a4b
+ c7d563f1e02eb4f54919ae707d6cc9573ca85434f3559b30
+ 78aeda0f601d877e;
+ aca23752615c82c1d454c4fc1462dcf3
+ 00aaf7bf9d75c663c54530549a
+ 86eec4ba8409465f
+ 875547667e2424abb2a30fde33b6e81c2b5c1c5629b262555c
+ a15c03b3d37d1f5fba858d394997e935c44985212cfaed5037
+ bd7dd7a68f95a476;
+ aca23752615c82c1d454c4fc1462dcf3
+ 0040da4cf416fc63c54530549a
+ 15801a12adb41e13223d9c4f
+ f1d25ee5bd3014d5eb7254c3c62ded9d1dbb7d
+ 0c9c100d74193c6d5679cd01b6418fff3a4fe4
+ 7cf0866237842658;
+ aca23752615c82c1d454c4fc1462dcf3
+ 002c2cbdfa28bf63c54530549a
+ d9808ff2b59b6a89bf9c4a82
+ 05bba8822b40f4803253fb91f0b5bcf60ee5dd95
+ b5b3b7fab03d662e1842333328466dd81dd8fe3d
+ 6f8c861ab1617dc3;
+ aca23752615c82c1d454c4fc1462dcf3
+ 0016230909f7cc63c54530549a
+ 9b85df31226b387fdf8ddd4d
+ 4eb993044b71beddc6ef3f287197e4d46e9f29e427
+ a0e19481ba549ce66fadd81937a09a4f542b2f421d
+ 12695462fd931591;
+ aca23752615c82c1d454c4fc1462dcf3
+ 00797b71e3c96963c54530549a
+ e7e6473a07dacca4
+ 9436254b379e38d73861ca027fc79b0440aba519e9e1dc
+ 0d22d68dc1d39934f8e5882c2058436a0cc58e03258b4e
+ 2bb39e01a568aba1f1ba;
+ aca23752615c82c1d454c4fc1462dcf3
+ 0083ae22deb9b163c54530549a
+ a1c6b900678806b8
+ 37709803b3fff94ffac1150b28a3cef1bf4feea0ff19541c
+ 3103c511e43dc5e01aba07db0b84a443a1e3425983c3fe7e
+ 19c626fd947eafb9c1b3;
+ aca23752615c82c1d454c4fc1462dcf3
+ 006541e08f013463c54530549a
+ ea6abbb54793ecc2
+ eb0e990f88cfb0e78c1d6196890f8b6fa7787fe2dd85a72355
+ a449f8b7a3c9d0c3fca9a6e7a89953fdbbb5d4d05dc77f67ae
+ 4efbc470d8a0b1c4f967;
+ aca23752615c82c1d454c4fc1462dcf3
+ 00ede32aa3875a63c54530549a
+ 869cbaf565fbb429d4603ace
+ 6cd5e33d9e5ff526e21b24f40d6b15e5ed25fb
+ 450c728aac9be3105cbe74653ffd52feb4a5ad
+ d6db7bc4dfdfc165dd93;
+ aca23752615c82c1d454c4fc1462dcf3
+ 0073331529b3db63c54530549a
+ 934cae407d3e300ae7111b43
+ e9a5e8b187d1e7baa3ad94fcf9e1b25aff726259
+ 5f7716b16a6218b2a44033c29260df1d75caadd4
+ 583c50b41845b3867f21;
+ aca23752615c82c1d454c4fc1462dcf3
+ 00cdf8f729be7363c54530549a
+ 6dbf3223e9758ce37ed8e2a9
+ ab8db40bc61588976d79d96e3012f0ff60e37e0732
+ 220bb8f4aba55c7d573f1f2fbd3d78a4361c665f51
+ 659f6d2e866db4de0e97;
+
+ ## From NIST SP800-38C.
+ 404142434445464748494a4b4c4d4e4f
+ 10111213141516
+ 0001020304050607
+ 20212223
+ 7162015b
+ 4dac255d;
+ 404142434445464748494a4b4c4d4e4f
+ 1011121314151617
+ 000102030405060708090a0b0c0d0e0f
+ 202122232425262728292a2b2c2d2e2f
+ d2a1f0e051ea5f62081a7792073d593d
+ 1fc64fbfaccd;
+ 404142434445464748494a4b4c4d4e4f
+ 101112131415161718191a1b
+ 000102030405060708090a0b0c0d0e0f10111213
+ 202122232425262728292a2b2c2d2e2f3031323334353637
+ e3b201a9f5b71a7a9b1ceaeccd97e70b6176aad9a4428aa5
+ 484392fbc1b09951;
+
+ ## Other NIST examples.
+ 404142434445464748494a4b4c4d4e4f
+ 10111213141516
+ ""
+ 202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f
+ 7162015bc051951e5918aeaf3c11f3d4ac363f8d5b6af3d369603b04f24cae29964e2f2bf9d31143f72527ce2db402eab7660e4a10b08e82266517cdf60267f9
+ c66b655c;
+ 404142434445464748494A4B4C4D4E4F
+ 10111213141516
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f
+ ""
+ ""
+ e84023f8;
+ 404142434445464748494a4b4c4d4e4f5051525354555657
+ 10111213141516
+ 0001020304050607
+ 20212223
+ 18ee1730
+ c8c326d5;
+ 404142434445464748494a4b4c4d4e4f5051525354555657
+ 1011121314151617
+ 000102030405060708090a0b0c0d0e0f
+ 202122232425262728292a2b2c2d2e2f
+ 2232b6e0924148ae7239bcbd1a0f7ecb
+ 56e9cc28aa67;
+ 404142434445464748494a4b4c4d4e4f5051525354555657
+ 101112131415161718191a1b
+ 000102030405060708090a0b0c0d0e0f10111213
+ 202122232425262728292a2b2c2d2e2f3031323334353637
+ 8081316fd89624d62ce7637fb94995b6631c50d61586de01
+ 42366952505f995a;
+ 404142434445464748494a4b4c4d4e4f5051525354555657
+ 10111213141516
+ ""
+ 202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f
+ 18ee1730f4490ea847a8e9c532c69f9c0a539a585c1e7b6a5af919f4819088a96ed632555098d3007e7d963c7bd013eb307671d0fbc39a0df4a26a9f4b9e4dad
+ c9ce2fbc;
+ 404142434445464748494a4b4c4d4e4f5051525354555657
+ 10111213141516
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f
+ ""
+ ""
+ f1fb2a57;
+ 404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f
+ 10111213141516
+ 0001020304050607
+ 20212223
+ 8ab1a874
+ 95fc0820;
+
+ 404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f
+ 1011121314151617
+ 000102030405060708090a0b0c0d0e0f
+ 202122232425262728292a2b2c2d2e2f
+ af1785fc0f5ea7d0cfba837246484497
+ 94b826c8849e;
+
+ 404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f
+ 101112131415161718191a1b
+ 000102030405060708090a0b0c0d0e0f10111213
+ 202122232425262728292a2b2c2d2e2f3031323334353637
+ 04f883aeb3bd0730eaf50bb6de4fa2212034e4e41b0e75e5
+ 2b48c8766f7e7649;
+
+ 404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f
+ 10111213141516
+ ""
+ 202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f
+ 8ab1a874f6853f2443a59500f78d17272d6d39dfa6d0e65107b10700c2ce9ee8663d3e2a01c2e12c32e9377442231920be53278f4f60a972b709bb16932936ba
+ 3fbd0fae;
+
+ 404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f
+ 10111213141516
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f
+ ""
+ ""
+ a6cf8230;
+
+ ## Locally generated tests.
+ 60d7bcda163547d348b7551195e77022
+ 907dd1dff7dac5c9941d26
+ ""
+ ""
+ ""
+ cf28ba78;
+ d0c6eb14ad568f86edd1dc9268eeee53
+ 3285a6ed810c9b689daaa9
+ 06
+ ""
+ ""
+ f258e4d7;
+ 0d2d4b6003062365b0a54364c76c160f
+ 11896c4794846ecfa14a71
+ ""
+ 30
+ d6
+ 0c31647b;
+ c9f137120634c9519848a877ff77bf79
+ 192a5b50ade5d9cd73
+ 9a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21
+ 635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49
+ 41b97c9616d0af69288f13e20d74901645bc9b5263044121e5562fa5b0e5ef40a2639909c2e07e329cc50737613a2c53
+ e992acc597653980b46bc43fd471eb5f;
+ ae1d50c38201a894476b3f102b752eb9
+ 529533966f27043eb6
+ 21b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6
+ c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26afa3
+ 8c314091d48b18dba473f0180ebfa878c920562f0d3c63303cafd8b92e31c35ca8e30e5dde711d30e7360b70030864de8d8156be5e
+ 672d9df3a0e99ed948e4f598a913b421;
+ 349829b94586306fed54154f8f28523c03d4de16
+ 00157846b710ee72807a22
+ ""
+ ""
+ ""
+ 9205b2da;
+ 19bfb474fd71d891f24bb65d1563259f9eb53b57
+ 1ea629c54d57dd2d42f708
+ 00
+ ""
+ ""
+ 9ae9b8a9;
+ df9fcbaca48b77dba189196d1ebba10b0467cb9f
+ c2712a199e533fa9156308
+ ""
+ cd
+ 19
+ fab4799d;
+ ec3f768281e040a9b9a222bd689aef66f5306ceb
+ 0c6b08ac8b0a22260c
+ 571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da
+ 6794c18b5337685a96ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf3
+ a11307a1d9df486ff782f6643324950ec651e2df47bab6ef1254fa7d04b59bca5f509bc9e781ed797105d39fb509de45
+ 27d12d4fb2bc29dc306d5c2240e4894c;
+ 0f1dad89d4b9b12012e4713df46795630e7952d2
+ 2bb02d7100b8b64937
+ 7d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d0798391805da0
+ 8da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7ca
+ 45adc79632d8fdc8470e9ea47e2523d2a9ad568b2817b5295c078756df3d7f584aaf4b4e9667023b719c1ef7ad9cb72bdf31746f56
+ f1855db5745f0561fd8113b2ff6006ce;
+ dcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a874498
+ ad0abef8bc4fcb70e27e98
+ ""
+ ""
+ ""
+ a84a331d;
+ ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4
+ ae985511265febd11c1647
+ 20
+ ""
+ ""
+ e4256cb2;
+ eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0c
+ fa9138ddc39908445608fe
+ ""
+ 95
+ 52
+ 87c71b52;
+ e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3
+ f9099c5ffb824173d7
+ 634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc
+ 9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911
+ b000328931c8a1484cae26f4f7be0415d58858fcff326136d37fd981492c5851163f68326cac9d4b80f29f5c157a28c2
+ 9b9c5705e2d569fc1b280731e4286027;
+ e32d65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4c9
+ 67c0a458cb948bdd40
+ 9b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a3e8128f8743d16687b7bb8de
+ b9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2ecccb4
+ d038ac6646cb2b6da23963eac488def0a233d63e097f9b981d322f96d6cad2d2c2be978d566a5afd8b20ecff4f1c8765ee5446c2a3
+ 28b572f708c9a6eb036444c0a9e8818c;
+ 4d65bad397abfaf529ee41cf
+ 9a05c7efedef3401539c51
+ ""
+ ""
+ ""
+ 66c301e7;
+ d2a90bbf7f1bfc338ab0ef57
+ 46ea8fdcccd213e33f7e8a
+ 57
+ ""
+ ""
+ df5a4e4e;
+ 18fd25014107c8e7d715a92a
+ dd9589d1f5c054b2d98351
+ ""
+ 46
+ 2a
+ 0c3bbfb2;
+ 05ec590294a319b9802068a9
+ f891bc5ba5afabf8c3
+ 122d12d7ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde9
+ 5759ac46fee6dda7abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4
+ 5c4a984366df29ee88817bba556a52b0c17ce5c3a337caac667c792cd1d7b705e3db87734963b51d606d8022346fc267
+ 1494a9ba0a649a71409b719d821d546f;
+ 563d405e51881e99027b8ab9
+ aea3ccf860b0009740
+ 763d96836c5f87b95460938de1288c69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7a3
+ aa7e740da967828e3604b35b15ffaa6c36800d9645563a308ba60076817523bd2abf1261b089d8f23a9c2835076a23faac2cdd6777
+ 73f618f0bfb917a6ca4f6b7872dbd148fa97bbf8ab044f3331410eef1be00037e9293d851e99ee70c65cad306c4fc0cee754ee1e5c
+ f1c35f66bbb6b69b6c7aa3e7ed23e47e;
+}
+
+rijndael-eax {
+ ## From Mihir Bellare, Phillip Rogaway, David Wagner, `The EAX Mode of
+ ## Operation (A Two-Pass Authenticated-Encryption Scheme Optimized for
+ ## Simplicity and Efficiency)'.
+
+ 233952dee4d5ed5f9b9c6d6ff80ff478
+ 62ec67f9c3a4a407fcb2a8c49031a8b3
+ 6bfb914fd07eae6b
+ ""
+ ""
+ e037830e8389f27b025a2d6527e79d01;
+ 91945d3f4dcbee0bf45ef52255f095a4
+ becaf043b0a23d843194ba972c66debd
+ fa3bfd4806eb53fa
+ f7fb
+ 19dd
+ 5c4c9331049d0bdab0277408f67967e5;
+ 01f74ad64077f2e704c0f60ada3dd523
+ 70c3db4f0d26368400a10ed05d2bff5e
+ 234a3463c1264ac6
+ 1a47cb4933
+ d851d5bae0
+ 3a59f238a23e39199dc9266626c40f80;
+ d07cf6cbb7f313bdde66b727afd3c5e8
+ 8408dfff3c1a2b1292dc199e46b7d617
+ 33cce2eabff5a79d
+ 481c9e39b1
+ 632a9d131a
+ d4c168a4225d8e1ff755939974a7bede;
+ 35b6d0580005bbc12b0587124557d2c2
+ fdb6b06676eedc5c61d74276e1f8e816
+ aeb96eaebe2970e9
+ 40d0c07da5e4
+ 071dfe16c675
+ cb0677e536f73afe6a14b74ee49844dd;
+ bd8e6e11475e60b268784c38c62feb22
+ 6eac5c93072d8e8513f750935e46da1b
+ d4482d1ca78dce0f
+ 4de3b35c3fc039245bd1fb7d
+ 835bb4f15d743e350e728414
+ abb8644fd6ccb86947c5e10590210a4f;
+ 7c77d6e813bed5ac98baa417477a2e7d
+ 1a8c98dcd73d38393b2bf1569deefc19
+ 65d2017990d62528
+ 8b0a79306c9ce7ed99dae4f87f8dd61636
+ 02083e3979da014812f59f11d52630da30
+ 137327d10649b0aa6e1c181db617d7f2;
+ 5fff20cafab119ca2fc73549e20f5b0d
+ dde59b97d722156d4d9aff2bc7559826
+ 54b9f04e6a09189a
+ 1bda122bce8a8dbaf1877d962b8592dd2d56
+ 2ec47b2c4954a489afc7ba4897edcdae8cc3
+ 3b60450599bd02c96382902aef7f832a;
+ a4a4782bcffd3ec5e7ef6d8c34a56123
+ b781fcf2f75fa5a8de97a9ca48e522ec
+ 899a175897561d7e
+ 6cf36720872b8513f6eab1a8a44438d5ef11
+ 0de18fd0fdd91e7af19f1d8ee8733938b1e8
+ e7f6d2231618102fdb7fe55ff1991700;
+ 8395fcf1e95bebd697bd010bc766aac3
+ 22e7add93cfc6393c57ec0b3c17d6b44
+ 126735fcc320d25a
+ ca40d7446e545ffaed3bd12a740a659ffbbb3ceab7
+ cb8920f87a6c75cff39627b56e3ed197c552d295a7
+ cfc46afc253b4652b1af3795b124ab6e;
+
+ ## Some local tests for additional edge cases, generated using the toy
+ ## implementation in Python.
+ 60d7bcda163547d348b7551195e77022
+ ""
+ ""
+ ""
+ ""
+ fc65784451ea97468ec025e17a709456;
+ 907dd1dff7dac5c9941d26d0c6eb14ad
+ 56
+ ""
+ ""
+ ""
+ d8da3364e510165ed5afd2aab762f5d2;
+ 8f86edd1dc9268eeee533285a6ed810c
+ ""
+ 9b
+ ""
+ ""
+ 715b06133d886f3b8fb8fdfcadd0fa5c;
+ 689daaa9060d2d4b6003062365b0a543
+ ""
+ ""
+ 64
+ 69
+ 16c192d8633a39465ce18da2ce132233;
+ c76c160f11896c4794846ecfa14a7130
+ c9f137120634c9519848a877ff77bf79
+ 192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8
+ cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505
+ 963801ede08bd2b86a3c33cf18c27d98c7c22f14c08621651e6094e72bcbd4bbf38f5e20814d465daa9c5929b9f59375
+ 180ad55fa758703dd6a4e345956705e5;
+ da1435dceaa7b1cc49ae1d50c38201a8
+ 94476b3f102b752eb9529533966f27
+ 043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbb
+ b18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac
+ 448792431ef5eb64efcfb2e6a9bb454d7ef09598ca4bc057d9cba969328ad75c05b7da7012e5ff1826dc3c981072fc9dce719cfffa
+ aeaa46b633b5c3ba7db2e404af2eb9a8;
+ 26afa3349829b94586306fed54154f8f28523c03
+ ""
+ ""
+ ""
+ ""
+ d0a749a3ae472501971c7521066a5c14;
+ d4de1600157846b710ee72807a2219bfb474fd71
+ d8
+ ""
+ ""
+ ""
+ 5998cfaef8d97abd4c8017aba424a845;
+ 91f24bb65d1563259f9eb53b571ea629c54d57dd
+ ""
+ 2d
+ ""
+ ""
+ 7ecfd7cde12120a79d65622bd02993f8;
+ 42f70800df9fcbaca48b77dba189196d1ebba10b
+ ""
+ ""
+ 04
+ 46
+ b4b2f22374e5416565ea5da09bd65726;
+ 67cb9fc2712a199e533fa9156308cdec3f768281
+ e040a9b9a222bd689aef66f5306ceb0c
+ 6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc81517
+ 84873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd
+ 78ebdb6a281df84204a58c3071a81ee62c604c4ff408d02ec9401bd284beba033e438279a8cf450bccc58ddb0480b0b1
+ 8f3edaf96c1c577c99d506fa9bdd342c;
+ 211499268878dbf30f1dad89d4b9b12012e4713d
+ f46795630e7952d22bb02d7100b8b6
+ 49377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d079839180
+ 5da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0
+ b81e04dfef276af4992a4daacad70a724bd2bc5f857d739b82781dab188f6c172f1dc3390ab9226f6a286bf89e3fd198ee3e781db4
+ 1096e8cbf9132840e22c4e9618a981c2;
+ b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a87
+ ""
+ ""
+ ""
+ ""
+ 8517441bde0b33302a5d73d756bbaea3;
+ 4498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc1
+ 88
+ ""
+ ""
+ ""
+ 2703e5e0acbf6d762e635e66e599c7e7;
+ d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c
+ ""
+ 8d
+ ""
+ ""
+ 21ba7e9152f7a188a570a435a9118dd7;
+ d0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc3
+ ""
+ ""
+ 99
+ 8f
+ 19edae1a9f72c3ec1a95456a7602fbea;
+ 08445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b8
+ 07e6daa089c3f9099c5ffb824173d763
+ 4c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9b
+ c597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e3
+ 7da2cbb1dbb96d57e6eae7f7463cdaf220f06e96bcce1303ef6c987de22fa64d62c89f8bef1676b6c9447b03575fce9a
+ 83e41c3c033397193406be50be532022;
+ 2d65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967
+ c0a458cb948bdd409b687fa3a6827b
+ 480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd205b70e04c
+ 091d205cdad9e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397abfa
+ 5c26f8ce44729fef7b23d7a08a6f770499d3efd779ec6975b549f418abdffc8a1fe5c279e41e3815b8667e96a4ad39aeef24bee42f
+ cd68c88ece3bead81778b31e8dbe34db;
+ f529ee41cf9a05c7efedef34
+ ""
+ ""
+ ""
+ ""
+ 9fa09ea950f21cf235e494490111462f;
+ 01539c51d2a90bbf7f1bfc33
+ 8a
+ ""
+ ""
+ ""
+ b694f1a079840c1a5306fa86a0d4bba3;
+ b0ef5746ea8fdcccd213e33f
+ ""
+ 7e
+ ""
+ ""
+ 91c2e974c399c84bdff77b962441e1f3;
+ 8a5718fd25014107c8e7d715
+ ""
+ ""
+ a9
+ 14
+ 279ad0e41ab70a6751f9fbd01030784e;
+ 2add9589d1f5c054b2d98351
+ 4605ec590294a319b9802068a9f891bc
+ 5ba5afabf8c3122d12d7ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725c
+ b2dac07ecde95759ac46fee6dda7abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d9803
+ cb3a052da8d3fc8c6e40de726ef40596a871d596df7b7c33b11467ba4ab39210df119a6e202267b44f86db3b4074c886
+ 4ea05695bbf7f261c4e76415e3642945;
+ 98bd94e66eb4563d405e5188
+ 1e99027b8ab9aea3ccf860b0009740
+ 763d96836c5f87b95460938de1288c69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7a3
+ aa7e740da967828e3604b35b15ffaa6c36800d9645563a308ba60076817523bd2abf1261b089d8f23a9c2835076a23faac2cdd6777
+ 03f7e555335edc0f776c210da68ddceda30e7b6d11f62aab60a17f443e6000c31ca8927b28791f8b5dcff245c82b63ebca8cdbeb9a
+ a860ca21635e5d2c1fa19d96a4c394fa;
+}
+
+rijndael-gcm {
+
+ ## NIST examples.
+ feffe9928665731c6d6a8f9467308308
+ cafebabefacedbaddecaf888
+ ""
+ ""
+ ""
+ 3247184b3c4f69a44dbcd22887bbb418;
+ feffe9928665731c6d6a8f9467308308
+ cafebabefacedbaddecaf888
+ ""
+ d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
+ 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985
+ 4d5c2af327cd64a62cf35abd2ba6fab4;
+ feffe9928665731c6d6a8f9467308308
+ cafebabefacedbaddecaf888
+ 3ad77bb40d7a3660a89ecaf32466ef97f5d3d58503b9699de785895a96fdbaaf43b1cd7f598ece23881b00e3ed0306887b0c785e27e8ad3f8223207104725dd4
+ ""
+ ""
+ 5f91d77123ef5eb9997913849b8dc1e9;
+ feffe9928665731c6d6a8f9467308308
+ cafebabefacedbaddecaf888
+ 3ad77bb40d7a3660a89ecaf32466ef97f5d3d58503b9699de785895a96fdbaaf43b1cd7f598ece23881b00e3ed0306887b0c785e27e8ad3f8223207104725dd4
+ d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
+ 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985
+ 64c0232904af398a5b67c10b53a5024d;
+ feffe9928665731c6d6a8f9467308308
+ cafebabefacedbaddecaf888
+ 3ad77bb40d7a3660a89ecaf32466ef97f5d3d585
+ d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+ 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091
+ f07c2528eea2fca1211f905e1b6a881b;
+
+ feffe9928665731c6d6a8f9467308308feffe9928665731c
+ cafebabefacedbaddecaf888
+ ""
+ ""
+ ""
+ c835aa88aebbc94f5a02e179fdcfc3e4;
+ feffe9928665731c6d6a8f9467308308feffe9928665731c
+ cafebabefacedbaddecaf888
+ ""
+ d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
+ 3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256
+ 9924a7c8587336bfb118024db8674a14;
+ feffe9928665731c6d6a8f9467308308feffe9928665731c
+ cafebabefacedbaddecaf888
+ 3ad77bb40d7a3660a89ecaf32466ef97f5d3d58503b9699de785895a96fdbaaf43b1cd7f598ece23881b00e3ed0306887b0c785e27e8ad3f8223207104725dd4
+ ""
+ ""
+ 02cc773bc919f4e1c5e9c54313bface0;
+ feffe9928665731c6d6a8f9467308308feffe9928665731c
+ cafebabefacedbaddecaf888
+ 3ad77bb40d7a3660a89ecaf32466ef97f5d3d58503b9699de785895a96fdbaaf43b1cd7f598ece23881b00e3ed0306887b0c785e27e8ad3f8223207104725dd4
+ d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
+ 3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade256
+ 3b9153b4e7318a5f3bbeac108f8a8edb;
+ feffe9928665731c6d6a8f9467308308feffe9928665731c
+ cafebabefacedbaddecaf888
+ 3ad77bb40d7a3660a89ecaf32466ef97f5d3d585
+ d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+ 3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710
+ 93ea28c659e269902a80acd208e7fc80;
+
+ feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+ cafebabefacedbaddecaf888
+ ""
+ ""
+ ""
+ fd2caa16a5832e76aa132c1453eeda7e;
+ feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+ cafebabefacedbaddecaf888
+ ""
+ d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
+ 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad
+ b094dac5d93471bdec1a502270e3cc6c;
+ feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+ cafebabefacedbaddecaf888
+ 3ad77bb40d7a3660a89ecaf32466ef97f5d3d58503b9699de785895a96fdbaaf43b1cd7f598ece23881b00e3ed0306887b0c785e27e8ad3f8223207104725dd4
+ ""
+ ""
+ de34b6dcd4cee2fdbec3cea01af1ee44;
+ feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+ cafebabefacedbaddecaf888
+ 3ad77bb40d7a3660a89ecaf32466ef97f5d3d58503b9699de785895a96fdbaaf43b1cd7f598ece23881b00e3ed0306887b0c785e27e8ad3f8223207104725dd4
+ d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
+ 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad
+ c06d76f31930fef37acae23ed465ae62;
+ feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+ cafebabefacedbaddecaf888
+ 3ad77bb40d7a3660a89ecaf32466ef97f5d3d585
+ d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+ 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662
+ e097195f4532da895fb917a5a55c6aa0;
+
+ ## IEEE tests for P802.1.
+ ad7a2bd03eac835a6f620fdcb506b345
+ 12153524c0895e81b2c28465
+ d609b1f056637a0d46df998d88e5222ab2c2846512153524c0895e8108000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233340001
+ ""
+ ""
+ f09478a9b09007d06f46e9b6a1da25dd;
+ ad7a2bd03eac835a6f620fdcb506b345
+ 12153524c0895e81b2c28465
+ d609b1f056637a0d46df998d88e52e00b2c2846512153524c0895e81
+ 08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a0002
+ 701afa1cc039c0d765128a665dab69243899bf7318ccdc81c9931da17fbe8edd7d17cb8b4c26fc81e3284f2b7fba713d
+ 4f8d55e7d3f06fd5a13c0c29b9d5b880;
+ 071b113b0ca743fecccf3d051f737382
+ f0761e8dcd3d000176d457ed
+ e20106d7cd0df0761e8dcd3d88e5400076d457ed08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a0003
+ ""
+ ""
+ 0c017bc73b227dfcc9bafa1c41acc353;
+ 071b113b0ca743fecccf3d051f737382
+ f0761e8dcd3d000176d457ed
+ e20106d7cd0df0761e8dcd3d88e54c2a76d457ed
+ 08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233340004
+ 13b4c72b389dc5018e72a171dd85a5d3752274d3a019fbcaed09a425cd9b2e1c9b72eee7c9de7d52b3f3
+ d6a5284f4a6d3fe22a5d6c2b960494c3;
+ 013fe00b5f11be7f866d0cbbc55a7a90
+ 7cfde9f9e33724c68932d612
+ 84c5d513d2aaf6e5bbd2727788e523008932d6127cfde9f9e33724c608000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f0005
+ ""
+ ""
+ 217867e50c2dad74c28c3b50abdf695a;
+ 013fe00b5f11be7f866d0cbbc55a7a90
+ 7cfde9f9e33724c68932d612
+ 84c5d513d2aaf6e5bbd2727788e52f008932d6127cfde9f9e33724c6
+ 08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b0006
+ 3a4de6fa32191014dbb303d92ee3a9e8a1b599c14d22fb080096e13811816a3c9c9bcf7c1b9b96da809204e29d0e2a7642
+ bfd310a4837c816ccfa5ac23ab003988;
+ 88ee087fd95da9fbf6725aa9d757b0cd
+ 7ae8e2ca4ec500012e58495c
+ 68f2e77696ce7ae8e2ca4ec588e541002e58495c08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d0007
+ ""
+ ""
+ 07922b8ebcf10bb2297588ca4c614523;
+ 88ee087fd95da9fbf6725aa9d757b0cd
+ 7ae8e2ca4ec500012e58495c
+ 68f2e77696ce7ae8e2ca4ec588e54d002e58495c
+ 08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748490008
+ c31f53d99e5687f7365119b832d2aae70741d593f1f9e2ab3455779b078eb8feacdfec1f8e3e5277f8180b43361f6512adb16d2e38548a2c719dba7228d840
+ 88f8757adb8aa788d8f65ad668be70e7;
+
+ e3c08a8f06c6e3ad95a70557b23f75483ce33021a9c72b7025666204c69c0b72
+ 12153524c0895e81b2c28465
+ d609b1f056637a0d46df998d88e5222ab2c2846512153524c0895e8108000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233340001
+ ""
+ ""
+ 2f0bc5af409e06d609ea8b7d0fa5ea50;
+ e3c08a8f06c6e3ad95a70557b23f75483ce33021a9c72b7025666204c69c0b72
+ 12153524c0895e81b2c28465
+ d609b1f056637a0d46df998d88e52e00b2c2846512153524c0895e81
+ 08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a0002
+ e2006eb42f5277022d9b19925bc419d7a592666c925fe2ef718eb4e308efeaa7c5273b394118860a5be2a97f56ab7836
+ 5ca597cdbb3edb8d1a1151ea0af7b436;
+ 691d3ee909d7f54167fd1ca0b5d769081f2bde1aee655fdbab80bd5295ae6be7
+ f0761e8dcd3d000176d457ed
+ e20106d7cd0df0761e8dcd3d88e5400076d457ed08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a0003
+ ""
+ ""
+ 35217c774bbc31b63166bcf9d4abed07;
+ 691d3ee909d7f54167fd1ca0b5d769081f2bde1aee655fdbab80bd5295ae6be7
+ f0761e8dcd3d000176d457ed
+ e20106d7cd0df0761e8dcd3d88e54c2a76d457ed
+ 08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f30313233340004
+ c1623f55730c93533097addad25664966125352b43adacbd61c5ef3ac90b5bee929ce4630ea79f6ce519
+ 12af39c2d1fdc2051f8b7b3c9d397ef2;
+ 83c093b58de7ffe1c0da926ac43fb3609ac1c80fee1b624497ef942e2f79a823
+ 7cfde9f9e33724c68932d612
+ 84c5d513d2aaf6e5bbd2727788e523008932d6127cfde9f9e33724c608000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f0005
+ ""
+ ""
+ 6ee160e8faeca4b36c86b234920ca975;
+ 83c093b58de7ffe1c0da926ac43fb3609ac1c80fee1b624497ef942e2f79a823
+ 7cfde9f9e33724c68932d612
+ 84c5d513d2aaf6e5bbd2727788e52f008932d6127cfde9f9e33724c6
+ 08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b0006
+ 110222ff8050cbece66a813ad09a73ed7a9a089c106b959389168ed6e8698ea902eb1277dbec2e68e473155a15a7daeed4
+ a10f4e05139c23df00b3aadc71f0596a;
+ 4c973dbc7364621674f8b5b89e5c15511fced9216490fb1c1a2caa0ffe0407e5
+ 7ae8e2ca4ec500012e58495c
+ 68f2e77696ce7ae8e2ca4ec588e541002e58495c08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d0007
+ ""
+ ""
+ 00bda1b7e87608bcbf470f12157f4c07;
+ 4c973dbc7364621674f8b5b89e5c15511fced9216490fb1c1a2caa0ffe0407e5
+ 7ae8e2ca4ec500012e58495c
+ 68f2e77696ce7ae8e2ca4ec588e54d002e58495c
+ 08000f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748490008
+ ba8ae31bc506486d6873e4fce460e7dc57591ff00611f31c3834fe1c04ad80b66803afcf5b27e6333fa67c99da47c2f0ced68d531bd741a943cff7a6713bd0
+ 2611cd7daa01d61c5c886dc1a8170107;
+
+ ## From `The Galois/Counter Mode of Operation' by David McGrew and John
+ ## Viega. Some of these were duplicated in the NIST examples above, and so
+ ## are omitted here.
+ 00000000000000000000000000000000
+ 000000000000000000000000
+ ""
+ ""
+ ""
+ 58e2fccefa7e3061367f1d57a4e7455a;
+ 00000000000000000000000000000000
+ 000000000000000000000000
+ ""
+ 00000000000000000000000000000000
+ 0388dace60b6a392f328c2b971b2fe78
+ ab6e47d42cec13bdf53a67b21257bddf;
+ feffe9928665731c6d6a8f9467308308
+ cafebabefacedbaddecaf888
+ feedfacedeadbeeffeedfacedeadbeefabaddad2
+ d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+ 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091
+ 5bc94fbc3221a5db94fae95ae7121a47;
+ feffe9928665731c6d6a8f9467308308
+ cafebabefacedbad
+ feedfacedeadbeeffeedfacedeadbeefabaddad2
+ d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+ 61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598
+ 3612d2e79e3b0785561be14aaca2fccb;
+ feffe9928665731c6d6a8f9467308308
+ 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b
+ feedfacedeadbeeffeedfacedeadbeefabaddad2
+ d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+ 8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5
+ 619cc5aefffe0bfa462af43c1699d050;
+
+ 000000000000000000000000000000000000000000000000
+ 000000000000000000000000
+ ""
+ ""
+ ""
+ cd33b28ac773f74ba00ed1f312572435;
+ 000000000000000000000000000000000000000000000000
+ 000000000000000000000000
+ ""
+ 00000000000000000000000000000000
+ 98e7247c07f0fe411c267e4384b0f600
+ 2ff58d80033927ab8ef4d4587514f0fb;
+ feffe9928665731c6d6a8f9467308308feffe9928665731c
+ cafebabefacedbaddecaf888
+ feedfacedeadbeeffeedfacedeadbeefabaddad2
+ d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+ 3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710
+ 2519498e80f1478f37ba55bd6d27618c;
+ feffe9928665731c6d6a8f9467308308feffe9928665731c
+ cafebabefacedbad
+ feedfacedeadbeeffeedfacedeadbeefabaddad2
+ d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+ 0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f7
+ 65dcc57fcf623a24094fcca40d3533f8;
+ feffe9928665731c6d6a8f9467308308feffe9928665731c
+ 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b
+ feedfacedeadbeeffeedfacedeadbeefabaddad2
+ d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+ d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e4581e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373b
+ dcf566ff291c25bbb8568fc3d376a6d9;
+
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 000000000000000000000000
+ ""
+ ""
+ ""
+ 530f8afbc74536b9a963b4f1c4cb738b;
+ 0000000000000000000000000000000000000000000000000000000000000000
+ 000000000000000000000000
+ ""
+ 00000000000000000000000000000000
+ cea7403d4d606b6e074ec5d3baf39d18
+ d0d1c8a799996bf0265b98b5d48ab919;
+ feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+ cafebabefacedbaddecaf888
+ feedfacedeadbeeffeedfacedeadbeefabaddad2
+ d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+ 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662
+ 76fc6ece0f4e1768cddf8853bb2d551b;
+ feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+ cafebabefacedbad
+ feedfacedeadbeeffeedfacedeadbeefabaddad2
+ d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+ c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f
+ 3a337dbf46a792c45e454913fe2ea8f2;
+ feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+ 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b
+ feedfacedeadbeeffeedfacedeadbeefabaddad2
+ d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+ 5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f
+ a44a8266ee1c8eb0c8b5d4cf5ae9f19a;
+
+ ## Further home-made tests, made using the toy Python implementation.
+ 60d7bcda163547d348b7551195e77022
+ ""
+ ""
+ ""
+ ""
+ 58b01ea630bccf61f3b34c172d152383;
+ 907dd1dff7dac5c9941d26d0c6eb14ad
+ 56
+ ""
+ ""
+ ""
+ 4728c593444566c1f955bbf6b3d38240;
+ 8f86edd1dc9268eeee533285a6ed810c
+ ""
+ 9b
+ ""
+ ""
+ d13020f394c38a8e22c46ccd91d10d77;
+ 689daaa9060d2d4b6003062365b0a543
+ ""
+ ""
+ 64
+ bc
+ 4daa100a72a49783462b47a93ae6bf16;
+ c76c160f11896c4794846ecfa14a7130
+ c9f137120634c9519848a877ff77bf79
+ 192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8
+ cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505
+ 382909981d309ca85ad62f43d0ed0d416f8040e3517772510ff95e50d9e411319e636647904a1c7ac2d857ed1996414b
+ 06ba36bc635adcbd1854fcef36614528;
+ da1435dceaa7b1cc49ae1d50c38201a8
+ 94476b3f102b752eb9529533
+ 966f27043eb621b7f65b000961040ef2f9b2fc
+ 5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93b
+ 7629cb94f9f709fd7c0988e50e935c3f95dc15a4f49207d62b3ba01fe62f0733842b97e72753292de7f4b3d0518ec30933d80bb3c93c5f2165
+ f894c92668f0264a7f663568f38c3d71;
+ f4f2aad2605faee2b03fb648e27fff63
+ 102758fe2b69ac26afa3349829b945
+ 86306fed54154f8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9e
+ b53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e0
+ 08bcec80c6486cc37d15f4da0dd221864d01b6bf9726ea9de673625a80e07e1250da4071099ffc8b50dc5cd1bfaaac50abef3d1b5a
+ 9456d186568dd1aca2e61c96d2ae9998;
+ 40a9b9a222bd689aef66f5306ceb0c6b08ac8b0a
+ ""
+ ""
+ ""
+ ""
+ d18fdc91e2ace4c8f4d66cf473fb42db;
+ 22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95
+ 21
+ ""
+ ""
+ ""
+ 93bcc629e1dc644f4f002440da2c9cca;
+ 4ade49cb3b6f5fe8368131115c037ba323fe1dc8
+ ""
+ 15
+ ""
+ ""
+ e87f107bb704c288cc68519cec9fa3d8;
+ 1784873f0eb5b647da6794c18b5337685a96ed65
+ ""
+ ""
+ b9
+ c1
+ c59a50c109f521ba596b3bfdff74fe9d;
+ aca338527ef19b09c063c46f88de9fd41e72d7b9
+ 7e23e6eabdff3bcd211499268878dbf3
+ 0f1dad89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa92
+ 1451dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1
+ 8068670d29a2a061b8375eb1e34259255991e9fadde3c5662930c9d29fe66fa5d513bfd6f2201e1503974444c827154b
+ 67f81d876969b8f8af546599fb81b929;
+ ecdf3d264a7f16cb16c2e815f422cdf0c8e30308
+ be3c31e6bc58c0b7cadcb658
+ b970e47479a684b5aefa69a4cd52147ed12ca9
+ 86981a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720
+ 23d16173096538a850efd193113ce4664d122a0e5ef73a70b50b57304b62704f65b9b1b1167d3e9a3cc66f95b873a856a05de800a91c2d43bc
+ c2a7ef96a5228db104f6a11034e50f8a;
+ eef9eb1c8dd0b00951f284649016ed0045633185
+ 4bc78bf43966eb0cfa9138ddc39908
+ 445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d763
+ 4c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccb
+ 9ef6b1732748b5f4fee62e025d4fa736336574ede8e760c680d546ecd9c51a03b3bfea4f3eff602cacdf9822717325ffff92196aa2
+ 1279f19bf183b1499da8da81e174d2b8;
+ b2f294b38766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4f
+ ""
+ ""
+ ""
+ ""
+ 565ff4cb468ce9c2c53451df7cc70651;
+ fa91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff6
+ 77
+ ""
+ ""
+ ""
+ e5f4f21a54e3788920c3fda8e47a561a;
+ 8554acf1270485b203a3c1c4c967c0a458cb948bdd409b687fa3a682
+ ""
+ 7b
+ ""
+ ""
+ fea5e7d3d32a547d19d029133e417f4c;
+ 480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a3e8128f8
+ ""
+ ""
+ 74
+ 2c
+ a0b8a9979dfb02faac0cfd7798f31e6f;
+ 3d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b085
+ 1e5ca605ac8451399587011677508a15
+ dde524af3e2bee0646541a42c2ecccb44d65bad397abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf7f1bfc338a
+ b0ef5746ea8fdcccd213e33f7e8a5718fd25014107c8e7d715a92add9589d1f5c054b2d983514605ec590294a319b980
+ c5c15ee7953a0b74712d9cfe36c7270a94c265f1af75b48e9147b54bf3509bea55e58c6ef3d7e60db1270d6f5f56d37b
+ 94d5625b8c1c2dc0eb7914e717dd640f;
+ 2068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70d17d4569eaff
+ 59a332ba58d5d5589bfe0797
+ 53ee1a957eb6d6699e6b7ea2725cb2dac07ecd
+ e95759ac46fee6dda7abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4563d405e51881e99
+ 43f463f1b21cd0f9246af63db9eacb644edaa029de296e1e70d30a6d944e65ed2690d1a0abee3fc608b816f6b80cb15f044ea37d146f92f4c5
+ 3b78d38c982a0c529ad66d6243694de8;
+ 027b8ab9aea3ccf860b0009740763d96836c5f87b95460938de1288c
+ 69d80ea12ff4bb5f069b8a2e86041c
+ 1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c36800d9645563a308ba600768175
+ 23bd2abf1261b089d8f23a9c2835076a23faac2cdd67771cc667a8331f0a170b66283e4f834a06148f302c3973accd56f6f24e3395
+ d76bde841be1e0f1c79d55aba162df14df0d8d27a79006ae86206959988ee72bdc2f865964dfb9f9367c28ff87aefdd0ffa01d9d97
+ aaa345866f4b3dbee0f6213cac96bd7b;
+ 8b8c2e2352fd61e4fa8fec81
+ ""
+ ""
+ ""
+ ""
+ 059b6263146de5fb545a936fc848b0b4;
+ 6ac861a8b33779f09e7a10fc
+ 02
+ ""
+ ""
+ ""
+ 58624b8c9053c43796880707b3d67f20;
+ a8f48afa3080ee119a52a9a8
+ ""
+ 17
+ ""
+ ""
+ 687f0761db05bcdb0388336d76fd22e7;
+ e4f2b94b0820cab383a8cffe
+ ""
+ ""
+ ea
+ 18
+ 767802f12d42935d7b001884afc02a9c;
+ 7c486315799dc875fba578c8
+ ec4837898a92142b5b0677da1ac27311
+ 7b45bcfff5d5f8b6fde2893232a9f81d14517ffae475f6b94a43a67b3d380d2f9aaafe2dd721c0095c88088476892114
+ 50ba8095ffab1eaadf66fd22ac1976063e113ab61f813e28a1397a7974a1d7f4220c785fe426a5a0e80f678d40414784
+ f32ff4b45a2e730c569689c1778053d0a0d98ff6ca284a29d5dec2d196cabe0b2ff7cccd2d76677cfa6f7f3f327e95dc
+ 6a8c65bf4d69020ca3653fe92b8a0750;
+ 2941feeffdc2eb44dc8c0d5e
+ 8f444f7f4e0c893959b74dc2
+ 3a7bb40e7e0013e5150686d2301b43a15a84e8
+ 1d7f5cedaa49e2414ebf47970e560475cff206877de69146acc3ab6cf8556b7aa776945948d1b8834df2196c92ec1718dcdeee0d52d9539726
+ c4af011456e8d101166565373ad9e8f158794f83fd254b98c7c8b0fc4bf23d0c2dd3158db30946c967d9eab008d6a526e6c2bf28b0a615fd76
+ 81383ad066041311a2eb1ab37d6c14eb;
+ d2810391b3f9d10c39b07ae8
+ f08ce7cee4758a386a9943e97dedfb
+ e61e737882cd09c2b9a80f34c0fde11c2481b11fc76bfa4dbf710a9e544e0c536ca1e040f9ad5b04140d98
+ edabe08485290a4d87d13b07398a1458c2c6b61dbdbc1cccada8c1a0a9aabb6c4e3c3554f8fb1ef61614c270295dfc0ca6551ca4bd
+ 502ab4639cc0336813c1e56e627ca9fd05ae8a04bb2b5a5dd7c03a5a4fc64ec1b9222fb965ee6c675f52bf3815a88d8a0ab837ad7b
+ 66578408dd93abb230ea3124f859308d;
+}
+
+rijndael-ocb1 {
+ ## Rogaway's tests, from http://web.cs.ucdavis.edu/~rogaway/ocb/ocb-test.htm
+ 000102030405060708090a0b0c0d0e0f
+ 00000000000000000000000000000001
+ ""
+ ""
+ ""
+ 15d37dd7c890d5d6acab927bc0dc60ee;
+ 000102030405060708090a0b0c0d0e0f
+ 00000000000000000000000000000001
+ ""
+ 000102
+ fcd37d
+ 02254739a5e3565ae2dcd62c659746ba;
+ 000102030405060708090a0b0c0d0e0f
+ 00000000000000000000000000000001
+ ""
+ 000102030405060708090a0b0c0d0e0f
+ 37df8ce15b489bf31d0fc44da1faf6d6
+ dfb763ebdb5f0e719c7b4161808004df;
+ 000102030405060708090a0b0c0d0e0f
+ 00000000000000000000000000000001
+ ""
+ 000102030405060708090a0b0c0d0e0f10111213
+ 01a075f0d815b1a4e9c881a1bcffc3eb7003eb55
+ 753084144eb63b770b063c2e23cda0bb;
+ 000102030405060708090a0b0c0d0e0f
+ 00000000000000000000000000000001
+ ""
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ 01a075f0d815b1a4e9c881a1bcffc3eb4afcbb7fedc08ca8654c6d304d1612fa
+ c14cbf2c1a1f1c3c137eadea1f2f2fcf;
+ 000102030405060708090a0b0c0d0e0f
+ 00000000000000000000000000000001
+ ""
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021
+ 01a075f0d815b1a4e9c881a1bcffc3ebd4903dd0025ba4aa837c74f121b0260fa95d
+ cf8341bb10820ccf14bdec56b8d7d6ab;
+ 000102030405060708090a0b0c0d0e0f
+ 00000000000000000000000000000001
+ ""
+ 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+ 4c9b676705ff2df05503872aa3d9e9b122c6b0ec060819146d9c887bad494417b63b4b2b3d9c3a4cd156856564c4a31be812a95d43e76ccf9811cc3a7613b0567bbcabf1a0f64f5245098c239ca7935765a7d402b01b671f1c600bc9a6823025c370a32da44a86911dce981ccaa7e3e720552bf8dd83918d8688e2347ba8691457bc25ab99a51a4388c3c7fad8a71e0c25fa185d2aa710dd9bb93cf2185ac950380732eef63549adcd451e70a0275b070fe1f9e338321aa57de832e1893f5febc0b2f0a6221d1aa187b9f152d20c259ed105c1a4be374993f4963074ef2676621109a03e628286124aefc8a3038b65103aa628f3e6bd6e1659ea0508185679d9a03b0794b914850cb4528293f7e992895a3e80337c23dbc95be1d3502cb9f8961e7dbe22898dc97b75fefaa75b4b3115969af05f54850489e007ce003d8023f490e37845f54d3c6dc3521fae9c34365091393f21139c96be6101a2bdc9dbc36902b5bd19686768154b011270157882f32dfef2a272be3cbf7e5d90ec1b6e374b4a4b806d83913e3df933e8caf5e02b1093b2a2991b34f98a41824a15b26a04a18f287024240d5347a2f3501546aac9c5b6e3f5010d9e2036c415d093892303050eaea499256eb83cba3ad4249537cbc250505024fe413965db1c41a77456711d50933249c63bd006716c4cc6ebf59c03c25a3ac3d06d7713c752f415f9ef59571885f38468c3f11bfd8111f839f080f544cb0c5ab9f87606287e314afe655510ceb8a62abcaef4e65e314f45b10e9858a175207356e9a8ac093f469ee587c18396f8965ce52e894b0bd29011b22f1e67abc16dcb948be141693fe31db635487285eeb4f8b4d5d13e511218759941850cd71fc898f8ba4cf1a4c23b3588dbf1e3e7c86efb113c8820e338a5d90d30c7d854a9ad7582d853d39cd3649cb67e3308c70bc75b732ae744aa126811034ff893829e554af51c83e1f004c3b7c9d0432978be459beaef6824b9cc5f370aa47b8d9edf583c3c84ef695705c95d59a428a675c5c788339ca737f2ec1cb6e83288b5bbfb6d1f81f47659f8f44118d76e900bdbc8094baa4bd950647abe22516a50bc85ea94410f985519076e34696b238262a00ebe889d58b09b81ee1f0b31f864a26978046ac24f1332559b6c5edc24748407e19f169c32d5d3f8ca6f71e4a5c2f72add2185857fde5749d5fd63f5b3658daa3dbaa1b0844fea3c8d2eb5e17febcfbfe44f4cf931129431ff51d6acce7e05107d6c055ad27beb185f7349ea060440a508b40186ec9732f84d21ae158969b671ac0d2ab823399220d75ec7cb50c29de3df974ae1e8c2465e3ecc207160c593443e424a57aaaee3c884632d979ccd0b6a239e1c3fdf777aa556a3c8815c2f8d1496a60048e2b971
+ ab335f725475e33e90ab8c1e4891596d;
+
+ 000102030405060708090a0b0c0d0e0f1011121314151617
+ 00000000000000000000000000000001
+ ""
+ ""
+ ""
+ b6e92be21127830a690f443f5ce8546d;
+
+ 000102030405060708090a0b0c0d0e0f1011121314151617
+ 00000000000000000000000000000001
+ ""
+ 000102
+ c21ef1
+ 09474d786d4640e823f52ff63ec5359a;
+
+ 000102030405060708090a0b0c0d0e0f1011121314151617
+ 00000000000000000000000000000001
+ ""
+ 000102030405060708090a0b0c0d0e0f
+ 3a709f22daf4c1bcf09cf1c2a0f5beff
+ 98d49eb3468988d06d7cb32c438f1f23;
+
+ 000102030405060708090a0b0c0d0e0f1011121314151617
+ 00000000000000000000000000000001
+ ""
+ 000102030405060708090a0b0c0d0e0f10111213
+ 8e951e2a2fb4ede0397cec6ba5dad5b22137f07d
+ 305767a31bc9e344f7f79843d1a268b1;
+
+ 000102030405060708090a0b0c0d0e0f1011121314151617
+ 00000000000000000000000000000001
+ ""
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ 8e951e2a2fb4ede0397cec6ba5dad5b247ff19f214fd464e821c63c26e4a11e9
+ 63cea28204ef06e5a21a8780ea05050d;
+
+ 000102030405060708090a0b0c0d0e0f1011121314151617
+ 00000000000000000000000000000001
+ ""
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021
+ 8e951e2a2fb4ede0397cec6ba5dad5b235e6b8a5dcb0bd0017bfe98111352d3edf3a
+ dfec4b4ed2f95c305d59d79edbf62833;
+
+ 000102030405060708090a0b0c0d0e0f1011121314151617
+ 00000000000000000000000000000001
+ ""
+ 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+ 1c97d826583970d083cca433773b02c34c0e6b7127d2258435bac13100c8672db6084c02171ba72b9937b1daccd14d0db1c322c708cc2da13486d772d82d93d12b69874a220573fc25fc05922700228c475ddeae653855a2c6d5f563f6e0724b7b2fe0fa066cba3223e010c5d1a51301a2ae1047409ae88c2779967283d50aa40ebb93e07dbde704f39c76c20cd1e1970bab196eacebab67b076bf901b4ed6f6ff066e230b540737d6856472ac02dce8b7a92aaa8890a47a13fc01bbce7ff902e3a7ede4685cd9bb926fecc27e915ad900f248d7ddd3cb9bff1b589196740c35ecf330e3812a6e0fcd2fd32212b0f0515629e7165cfe64857ec5ca2ad5c6eed654e27508a2c012b726e6931c4edc1fc00dd1d609f8659b24c0b4157f43fc33761d0a9b1fb1389068b600ce2f04cf475fb4483d32902b559cc40a589e97a82417241b92199595c6597dbd0e8dc08db9b6c0323a1d07812908be90c7785c66d1b295ab772793dc7e9725ef19da40b935c6ce10e404165388db6437621ffb08246f32b85a7ee9ca8bec10e3e973136c0b99552d8713bc6c892938ad72f79341f16eaaa7c8adfe45e2c627314c256bf0554dc1651ca77a80d79603cec892ffa58b092b5134c61d6dfba2a2132c75ce56db8cb1d852330a5c4a615645281457c2020391351f8dfa1297d45da234c0549991046d888b52175e1ed2ed3619474b5b270d6b5dcdd94e1a3f20594da51c8bd564e9694cb8b498eedd7a83569da5a209ba34e0fb29c43793097437fecc07e7709c8d64f15197b241ee930652872558c7ccb8c2a0e61e40637d1d587422d5f9f8f8eb25e44f7997058c051c4288356e5dd47e6022176f83c963eac7512cabc7fc8c408d448177e1b1671c82569a2318db142f8b94a60fe5b581c6895e03397a4d9b6f117fb534ad644ef7fafab3fe34c36b5d1544df4567fa94ba7a501ed20032d567bfea10f943170e5bf9b1aac21c0e25ae5f9b98272c75a401ba0185e46ff0c9b29caeb2314a507e2664df2208beb8a5c78563f68b49c3b59b650d18eb75a22296d06943b99239521c59736a10404d458e80ed9288879545c1f9b997036b9eb76c5d75afcd494736971dd27c3f0cbdc15e8cf8337c63417f861a15c324b44fc8b3e4ef6a1924f470aefd0abb6a965451d13835e8a8d9ef94add1d2a41f42c6ebc55045d7a1c6bb0ea3af9560220180fa7b623cc2c44d5cace341746e80289e0b7321178d770e2043a5b02560328c1a01ec4ab64ff98de111c5be5516657cff2f88d3a02643a587903f28a7f9d76cceca8a03671eeecdb2aa81e59de1171e5aaae08415533ceee30aa3ec4fbd551990c074d05c390dfbb1e5d1318e869be9e8417d49ccdaf801ebd42b0309718c36deb2965311710b6d26494a
+ d28b89f5339444767d637e8f1687d204;
+
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ 00000000000000000000000000000001
+ ""
+ ""
+ ""
+ 796b5fd2716b066932371c17993dcb5a;
+
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ 00000000000000000000000000000001
+ ""
+ 000102
+ a214d8
+ e31b3449bd1b85b257b404a76b5b86f2;
+
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ 00000000000000000000000000000001
+ ""
+ 000102030405060708090a0b0c0d0e0f
+ 8ed0923f5b2c650f31a5dd422463377f
+ 794904f519ab5376a30cf7771548e319;
+
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ 00000000000000000000000000000001
+ ""
+ 000102030405060708090a0b0c0d0e0f10111213
+ 6512529248df82feb506a7aeab3874f7201b6f79
+ 042ac0fd6956c2b0b4205dba0b889699;
+
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ 00000000000000000000000000000001
+ ""
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ 6512529248df82feb506a7aeab3874f7742c85da9d0d6cc91293ce0b333e0343
+ 6a91a07cb0bf508fee08b27b5fd9f80d;
+
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ 00000000000000000000000000000001
+ ""
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021
+ 6512529248df82feb506a7aeab3874f7ae809e2f4f88d6a6088f8d0122a7b9e723a5
+ 3ba0661c8a716b550150c9effe3b773c;
+
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ 00000000000000000000000000000001
+ ""
+ 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+ 1464d49f9ead864d5e77ed99198302409e459f2af179c73d2f0d0855d51591cbd9555d9a8542014e2b995e5399c1f804addaff1a2c4b5afe07fd88b7095d1129cbf93f9dad20c625fab0e63788ec4634f0ae06b6fc5c56bfe1b05860e03dc3284d7e2b3190eacee799f523677f942dee5192cfc6b5dddf09a16e2ae13055e9d1ee1d159b7fcea386133de34b92743caddef8c457884a7c5034a53ee23e08aa90086824401c25646561af0d594114b1ccb6627bff630fb17a6021b4f54942ed06f06326e54408019caba8f7231200d30dc548f8ec2c80e06b13d8ebe462c1cdf1c54065afabdb97ac8d8e5a1d065c59795fb55336f01e35a6f7cf8ddbf944e31a24717977c2f9f89aba3ca1ab7559a4f732d301b678ac63c9d5388665b1f9bc56bd67b80fe21f0d6ce4973c078213456b23700725174037fe8426503b0170ce5adda0dedc80f1e5d6701384951bbed58e6ec5912cd20429c5d85c61484136caa00c5f92763414e9f1bb50efc59c834142e5fbbab07f624f28fdee284c2b7322cf3e0682731f764a049fedf2ee8486e60bbd11de998f1dfde848999c806ef779bab0468b674d395883400cc6c05cdf5b51c5fbb181690502914edc42cd4752d9c5fb524adb37149c3199f2329ecaa92006047761f01581eafb96003491fef9ccdbf637c972842645b052ece338e02b6417e25f4f93aa808ec44d8b6efdd774ebac19a1756014a9bb71da38e7743d1617e44bae076f3183c7e50f5c0fd5488cb325edd500ad5e794c469b83a4655c95289dc520797f94cd04e834b1842f769236522cf79ae63ad4664b4745316142bc74ab27be915194eff2a2a1d740c83bffe28b8fe6cd1382ca8de806365275ed05baca90484b03ee87624f072905b69587c05be58aefd4e367257aa95ce3a6d0f65a5e7221c8f729727e3bd66f3d9e33f0d7b8f03ad31e62c837599e062a4c8681ec3276c31d58f2f3f2dd018b3c579fe50d7f911f8665bc064a08ae8ff6d87440e088b2162733ea6066ac70309600819f3f429232bb26376303fc82cd198dfc92382cfb3c8bc245984b845c51e6b5da8a9669e1d961f7182d0bb9757a99c0d72d4c037df2ca29661faf0db89fdce75bfb67031522096ce88f1ca6740f3dbbfd65fdf674a547d82d331abaaf1c5f0742a25c6f5ee0cfe288fb93e76d2fab4fde4904c2967303fcf2adb8bbd333b33728aca04b60dabdd08e0acafaffa97b02cb011db94687afa7bed3157d3a90814eb00e55b39cabfe9ef35bae62c80ad225cc34a0d7cce13c55ac107d00d7b37562222ac5d94cb73ff20d8947fb8ec63735280c0ce31aaca8fee02666f7a6fb2b44f1ebe0f090050f1036877ddb6705b1b622dbd1742f8ed2d985a5aeab4cd2a0e68d1ec3c6c1fec66446150d44
+ 826d7f68f3ce28e1e98191e92b23ab0a;
+
+ ## Homemade tests made with my toy implementation.
+ 60d7bcda163547d348b7551195e77022
+ 907dd1dff7dac5c9941d26d0c6eb14ad
+ ""
+ ""
+ ""
+ bbdd78ab7b6ed33bfbaf8438bf9df7ee;
+ 568f86edd1dc9268eeee533285a6ed81
+ 0c9b689daaa9060d2d4b6003062365b0
+ a5
+ ""
+ ""
+ f7922af46325a139e69abfbb9b999c4f;
+ 4364c76c160f11896c4794846ecfa14a
+ 7130c9f137120634c9519848a877ff77
+ ""
+ bf
+ 98
+ 8c5a791452eb9c1f37d7ab1bf637c432;
+ 79192a5b50ade5d9cd739a3d1f337f29
+ 549e6b0d27a4ba234085406a61365120
+ ""
+ 61f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9
+ bed87d0e2b6ab736c20081f2041691cdcaedfff9cdb08f5ff2b443fbb4990690a9bb03b8b801d3562f037c61c6d40929
+ bd5b4d2c9aeae8e9dd6baf02c53cc96d;
+ ff61cdbda3b3e9878731ebfedd4705e5
+ 05da1435dceaa7b1cc49ae1d50c38201
+ a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc
+ 520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605fae
+ b6cbe859f09a407e4a0e376a41b18a84eb07874e1b280fa3cdffa733c207c4b67ace2b90a406b1df6a2389593134796d
+ f370bf6c86cae4c4248040d74c191392;
+ e2b03fb648e27fff63102758fe2b69ac
+ 26afa3349829b94586306fed54154f8f
+ ""
+ 28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcb
+ 2ca95a4a033cd358788f8ffd43bbf820dc0982dfee8583eead310d571cb87e4472331362ff6820abf76cab3b4f405b41ad167f864d
+ e20d6b13e4691b43b82d5e16f77366b9;
+ aca48b77dba189196d1ebba10b0467cb
+ 9fc2712a199e533fa9156308cdec3f76
+ 8281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95
+ 214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063
+ 8c3ebaaf931dd282e77df4bf8c242a81593282df72cf91df24dc0bd8f6559f404058b9885529821083839944713def901330eebe75
+ 2d965094a4c93d801be22ba3faa198d9;
+ c46f88de9fd41e72d7b97e23e6eabdff3bcd2114
+ 99268878dbf30f1dad89d4b9b12012e4
+ ""
+ ""
+ ""
+ 8d524a5f17704ae5983de23c8c09fe82;
+ 713df46795630e7952d22bb02d7100b8b649377d
+ 20a8f083455b663e4ee1315f3c8f2aeb
+ fa
+ ""
+ ""
+ 9ea050885c272134d9056a4a94dba2dc;
+ 921451dcd1af5813b70d30ce2f1fef6ef315d079
+ 8391805da08da3aefc5f8584b7c5e617
+ ""
+ 66
+ 93
+ 813637682fa8878156badce86a0243fa;
+ 9c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb
+ 16c2e815f422cdf0c8e30308be3c31e6
+ ""
+ bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a874498ad0abef8bc4fcb70e27e98ef1f0446
+ dd538bb0839a0a7925c5a2aaf2cac28de820d307023f2ab4f2ffa04cef224b155ab948ad399e65a9ea8477aea35f29e2
+ e00806f1d623829ca51eeda7493528e9;
+ b42fb144d44b6d00f06dc188d472a784e0c6f211
+ 95a3b9f4ae985511265febd11c164720
+ eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a
+ 9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd1901073147
+ 4a2e9698c0d7ac74177739a07570f0f6afd2e3f3b6e9badbdbd95fdfc747dbbc7c1c8bceb40e423e1b2fa560ed2da50d
+ f13efea41ebf09ce14655687cb20a908;
+ 17a77456f3ff669c732b58db8f48af65f7cc9e3f
+ b90e1721b730374ffc9bc597f56ccbb2
+ ""
+ f294b38766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd
+ 672edb9395d87cc48fab9727017091e7a6d09f7977fbbfe77f9669485aaeca7a4d54662565aae03033ae925528e9880d33766cafcf
+ a8ff24657308e7d34115b33ff27ff795;
+ 1ff6778554acf1270485b203a3c1c4c967c0a458
+ cb948bdd409b687fa3a6827b480aa3a4
+ c84cef64f6c9b53bf8f957f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd205b70e04c091d205c
+ dad9e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397abfaf529ee41
+ 367a16e4adbc471e15eed3d0415714c61a67e93f44b5890d17f9d29991bae8406d317e7064c765278d7370f6534462f6eb2db66b23
+ 79a7bbc9be788ebb4b94fe94f3f74439;
+ cf9a05c7efedef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdc
+ ccd213e33f7e8a5718fd25014107c8e7
+ ""
+ ""
+ ""
+ 12f235dbf2dc24a51ec9211ba16494bd;
+ d715a92add9589d1f5c054b2d983514605ec590294a319b9802068a9
+ f891bc5ba5afabf8c3122d12d7ff3c41
+ 12
+ ""
+ ""
+ eb5d7e61788af1e2d62a0023cbee8ce8;
+ 2d70d17d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d669
+ 9e6b7ea2725cb2dac07ecde95759ac46
+ ""
+ fe
+ 65
+ 80cbf647b155069f455e35ce699db1b6;
+ e6dda7abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9
+ cf44bbc8c6254d980398bd94e66eb456
+ ""
+ 3d405e51881e99027b8ab9aea3ccf860b0009740763d96836c5f87b95460938de1288c69d80ea12ff4bb5f069b8a2e86
+ 5b2913b5bd5d4155174de957631d366c398a890cdcdef62c8a7882229522d3b944a1b0cc2d958910469f001ff60f4d05
+ fd4cff3dc0c58f0743b0bd9bc4e7b346;
+ 041c1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15
+ ffaa6c36800d9645563a308ba6007681
+ 7523bd2abf1261b089d8f23a9c2835076a23faac2cdd67771cc667a8331f0a170b66283e4f834a06148f302c3973accd
+ 56f6f24e33958b8c2e2352fd61e4fa8fec816ac861a8b33779f09e7a10fc02a8f48afa3080ee119a52a9a817e4f2b94b
+ 79b025b6d15120b9cc79ceb62cfe0479248b47f4b6318deeffe7ff11688460479331326370bac61dbec32ba5571d65d8
+ ce1ea3a0bfda4a072c98376f259ed0d3;
+ 0820cab383a8cffeea7c486315799dc875fba578c8ec4837898a9214
+ 2b5b0677da1ac273117b45bcfff5d5f8
+ ""
+ b6fde2893232a9f81d14517ffae475f6b94a43a67b3d380d2f9aaafe2dd721c0095c8808847689211450ba8095ffab1eaadf66fd22
+ 42075fba1b912e07c6f10e6356f6ccc84c60f34ea054dec4e4cdc39eb8f5066218b61d9cd799d28281e84d2d5f0138c944f1074b2a
+ 2889c19baf58c2061aa386bb60bf5c94;
+ ac1976063e113ab61f813e28a1397a7974a1d7f4220c785fe426a5a0
+ e80f678d404147842941feeffdc2eb44
+ dc8c0d5e8f444f7f4e0c893959b74dc23a7bb40e7e0013e5150686d2301b43a15a84e81d7f5cedaa49e241
+ 4ebf47970e560475cff206877de69146acc3ab6cf8556b7aa776945948d1b8834df2196c92ec1718dcdeee0d52d9539726d2810391
+ b270a45c7bb349e1dfbc9226da556d1916cb8eee0acc23671a875ba1bab176be7067e6ac38c492bef6c908881eed86e3fa34ba13bf
+ dd48047480fa2218d080933718dfa7dc;
+ b3f9d10c39b07ae8f08ce7ce
+ e4758a386a9943e97dedfbe61e737882
+ ""
+ ""
+ ""
+ aec3dd3d7d4d41c121f6da813bc52c6f;
+ cd09c2b9a80f34c0fde11c24
+ 81b11fc76bfa4dbf710a9e544e0c536c
+ a1
+ ""
+ ""
+ 1fb81cfb59ee9a075fc17a01fb0acb9e;
+ e040f9ad5b04140d98edabe0
+ 8485290a4d87d13b07398a1458c2c6b6
+ ""
+ 1d
+ cc
+ 2efc465c99ba1057c7dce6bf82f04a7d;
+ bdbc1cccada8c1a0a9aabb6c
+ 4e3c3554f8fb1ef61614c270295dfc0c
+ ""
+ a6551ca4bdb75359f91cb9d921056b7de74fc9a9b37154ce6c0b396179d31f06a1dd5982cbc0d7cb23841da1ae8f4ae4
+ c5b165d12e4f62edf355fad299ca25ee317c7c65deea43e27c93f43f66d87364b7dc60d20d5bcfde11e982c9275b2ebc
+ 5536fc1ce20b189e094233fed7a3da05;
+ 80cda98ad6cf2bacf6f9fd3f
+ 821330c43f3df6c2b3fac7cbcf96523d
+ 4723f91801325eb8553236651c96788d73d192ee53b3f3ebd66ddd98cedbe88e245de25b1593b70f8601562d90a9b59e
+ d034a867642d25d54756fa5c47f16f64b837bb4926214211a1c696ba172010abb433922a22d9fd881519165eb9d85197
+ 03cf2190ef314c60a1b51ab9c6d6cf1613779e05cb1f6dd1b54b16f1cebf6b964ee6f21a606b72e5751723d5ad6e284b
+ 7eb35f7458437efd2a95c97817396485;
+ a21cc34ac0d5ae7be8dbf98e
+ 4ffed2cf6b1372a5aa47b54fd9d70c70
+ ""
+ e117bf1cae71b3a56f0e7d839ea59cc783443d64f2ed6a29b96856beca34fd6544bcf86b799e2a1681160ccf055f0fd3001da597a1
+ 8a8f9e2516855b74721de0ee915f1759ae9aa036c52d9cbe43111de9015eb6bd353bef5bb4df325f466d8e2bd09303f912bc0576be
+ c67bc656ea1b155208501e080120205b;
+ 406d465b7b1419ea51cf858f
+ 938f6daafbd656445a09898eaa96ffc3
+ d1d2e31e4e34c94b8bfae64825ecd75a66d88eedb969ffe07669845ebb7a24c69f13d099f47166edf54538
+ e88fbf433a7ff212085179e79771f6eee7283ab178ef2b800d7b969da05780ffc1ba78c70dda7a4ca2a25e771702fb1901ecfc8a95
+ 15d8d8bfdd4b5fbe0885d060fc15bb2763c2d4aad2d18df548ed258db51d9cfd866b4e7798650061e447291f45ebe5da37635d468d
+ 329d67984dc92e926bf2c0698fba9e2b;
+}
+
+rijndael-pmac1 {
+ ## Rogaway's tests, from http://web.cs.ucdavis.edu/~rogaway/ocb/pmac-test.htm
+ 000102030405060708090a0b0c0d0e0f
+ ""
+ 4399572cd6ea5341b8d35876a7098af7;
+ 000102030405060708090a0b0c0d0e0f
+ 000102
+ 256ba5193c1b991b4df0c51f388a9e27;
+ 000102030405060708090a0b0c0d0e0f
+ 000102030405060708090a0b0c0d0e0f
+ ebbd822fa458daf6dfdad7c27da76338;
+ 000102030405060708090a0b0c0d0e0f
+ 000102030405060708090a0b0c0d0e0f10111213
+ 0412ca150bbf79058d8c75a58c993f55;
+ 000102030405060708090a0b0c0d0e0f
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ e97ac04e9e5e3399ce5355cd7407bc75;
+ 000102030405060708090a0b0c0d0e0f
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021
+ 5cba7d5eb24f7c86ccc54604e53d5512;
+ 000102030405060708090a0b0c0d0e0f
+ 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+ c2c9fa1d9985f6f0d2aff915a0e8d910;
+ 000102030405060708090a0b0c0d0e0f1011121314151617
+ ""
+ 0d63b2b2c276de9306b2f37e36dabe49;
+ 000102030405060708090a0b0c0d0e0f1011121314151617
+ 000102
+ 5b1cbc4340752742d8828a7aa2c3197d;
+ 000102030405060708090a0b0c0d0e0f1011121314151617
+ 000102030405060708090a0b0c0d0e0f
+ 0787415737989bc1a2e124c991e400e1;
+ 000102030405060708090a0b0c0d0e0f1011121314151617
+ 000102030405060708090a0b0c0d0e0f10111213
+ 156a7c21121cc773a731e05ab618c6bb;
+ 000102030405060708090a0b0c0d0e0f1011121314151617
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ 654a145904dc97da9f68318b180970b9;
+ 000102030405060708090a0b0c0d0e0f1011121314151617
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021
+ b5ff2016878e834438aa1ff624bfa09c;
+ 000102030405060708090a0b0c0d0e0f1011121314151617
+ 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+ d3aec29036298bc11a2905f53773ff50;
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ ""
+ e620f52fe75bbe87ab758c0624943d8b;
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ 000102
+ ffe124cc152cfb2bf1ef5409333c1c9a;
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ 000102030405060708090a0b0c0d0e0f
+ 853fdbf3f91dcd36380d698a64770bab;
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ 000102030405060708090a0b0c0d0e0f10111213
+ 7711395fbe9dec19861aeb96e052cd1b;
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ 08fa25c28678c84d383130653e77f4c0;
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021
+ edd8a05f4b66761f9eee4feb4ed0c3a1;
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+ 69aa77f231eb0cdff960f5561d29a96e;
+
+ ## Homemade tests made with my toy implementation.
+ 60d7bcda163547d348b7551195e77022
+ ""
+ f179b2c8e7020f9992e161128568d833;
+ 907dd1dff7dac5c9941d26d0c6eb14ad
+ 56
+ 335ab1737aaadac9f7d949ab7dc22fb5;
+ 8f86edd1dc9268eeee533285a6ed810c
+ 9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a877ff77
+ bb8edccea3819962f3207d2494d63229;
+ bf79192a5b50ade5d9cd739a3d1f337f
+ 29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21
+ 2ecd8200722cfe2378e956131b67d64e;
+ 635c6d62c9269029df3e6057acc87638f5080467
+ ""
+ 5defdf6083418cf3d45824aa490a4d81;
+ 33d9ff61cdbda3b3e9878731ebfedd4705e505da
+ 14
+ 6c60b9db748a6bdda7823422ed13e4cb;
+ 35dceaa7b1cc49ae1d50c38201a894476b3f102b
+ 752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3
+ c20cac43be40631325f8d7c9e65991ad;
+ a4f3ebbbb18ac6c95a97a48030370c33d090c542
+ 15abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26afa3349829
+ 3c963d5d3230ef4dc33ebd19f63965d9;
+ b94586306fed54154f8f28523c03d4de1600157846b710ee72807a22
+ ""
+ 050092b5cc9a2d131ea4450c057bbf3d;
+ 19bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d
+ 42
+ 16501f8ba884f8ace15138cefd2639a7;
+ f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e
+ 533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5c
+ 9738377d0ead6012bac60ae10ac4e5f7;
+ fb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc81517
+ 84873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6
+ 709f56ce90034a8882bebbfe453452c7;
+ eabdff3bcd211499268878db
+ ""
+ 697879320c2ee020acf13693df75c31d;
+ f30f1dad89d4b9b12012e471
+ 3d
+ 453c840a1c34bfeff73a653ad97150b4;
+ f46795630e7952d22bb02d71
+ 00b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d0798391805da0
+ aef316f092694e691d9fba0324d8397a;
+ 8da3aefc5f8584b7c5e61766
+ 9c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb6
+ 0638371148ba4e00b0cf138e026a7740;
+}
+
+rijndael-ocb2 {
+ ## Taken from https://tools.ietf.org/html/draft-krovetz-ocb-00.
+
+ 000102030405060708090a0b0c0d0e0f
+ 000102030405060708090a0b0c0d0e0f
+ ""
+ ""
+ ""
+ bf3108130773ad5ec70ec69e7875a7b0;
+ 000102030405060708090a0b0c0d0e0f
+ 000102030405060708090a0b0c0d0e0f
+ ""
+ 0001020304050607
+ c636b3a868f429bb
+ a45f5fdea5c088d1d7c8be37cabc8c5c;
+ 000102030405060708090a0b0c0d0e0f
+ 000102030405060708090a0b0c0d0e0f
+ ""
+ 000102030405060708090a0b0c0d0e0f
+ 52e48f5d19fe2d9869f0c4a4b3d2be57
+ f7ee49ae7aa5b5e6645db6b3966136f9;
+ 000102030405060708090a0b0c0d0e0f
+ 000102030405060708090a0b0c0d0e0f
+ ""
+ 000102030405060708090a0b0c0d0e0f1011121314151617
+ f75d6bc8b4dc8d66b836a2b08b32a636cc579e145d323beb
+ a1a50f822819d6e0a216784ac24ac84c;
+ 000102030405060708090a0b0c0d0e0f
+ 000102030405060708090a0b0c0d0e0f
+ ""
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ f75d6bc8b4dc8d66b836a2b08b32a636cec3c555037571709da25e1bb0421a27
+ 09ca6c73f0b5c6c5fd587122d75f2aa3;
+ 000102030405060708090a0b0c0d0e0f
+ 000102030405060708090a0b0c0d0e0f
+ ""
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324252627
+ f75d6bc8b4dc8d66b836a2b08b32a6369f1cd3c5228d79fd6c267f5f6aa7b231c7dfb9d59951ae9c
+ 9db0cdf880f73e3e10d4eb3217766688;
+ 000102030405060708090a0b0c0d0e0f
+ 000102030405060708090a0b0c0d0e0f
+ 0001020304050607
+ 0001020304050607
+ c636b3a868f429bb
+ 8d059589ec3b6ac00ca31624bc3af2c6;
+ 000102030405060708090a0b0c0d0e0f
+ 000102030405060708090a0b0c0d0e0f
+ 000102030405060708090a0b0c0d0e0f
+ 52e48f5d19fe2d9869f0c4a4b3d2be57
+ 4da4391bcac39d278c7a3f1fd39041e6;
+ 000102030405060708090a0b0c0d0e0f
+ 000102030405060708090a0b0c0d0e0f
+ 000102030405060708090a0b0c0d0e0f1011121314151617
+ 000102030405060708090a0b0c0d0e0f1011121314151617
+ f75d6bc8b4dc8d66b836a2b08b32a636cc579e145d323beb
+ 24b9ac3b9574d2202678e439d150f633;
+ 000102030405060708090a0b0c0d0e0f
+ 000102030405060708090a0b0c0d0e0f
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ f75d6bc8b4dc8d66b836a2b08b32a636cec3c555037571709da25e1bb0421a27
+ 41a977c91d66f62c1e1fc30bc93823ca;
+ 000102030405060708090a0b0c0d0e0f
+ 000102030405060708090a0b0c0d0e0f
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324252627
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324252627
+ f75d6bc8b4dc8d66b836a2b08b32a6369f1cd3c5228d79fd6c267f5f6aa7b231c7dfb9d59951ae9c
+ 65a92715a028acd4ae6aff4bfaa0d396;
+}
+
+rijndael-ocb3 {
+ ## Taken from RFC7253.
+
+ 000102030405060708090a0b0c0d0e0f
+ bbaa99887766554433221100
+ ""
+ ""
+ ""
+ 785407bfffc8ad9edcc5520ac9111ee6;
+ 000102030405060708090a0b0c0d0e0f
+ bbaa99887766554433221101
+ 0001020304050607
+ 0001020304050607
+ 6820b3657b6f615a
+ 5725bda0d3b4eb3a257c9af1f8f03009;
+ 000102030405060708090a0b0c0d0e0f
+ bbaa99887766554433221102
+ 0001020304050607
+ ""
+ ""
+ 81017f8203f081277152fade694a0a00;
+ 000102030405060708090a0b0c0d0e0f
+ bbaa99887766554433221103
+ ""
+ 0001020304050607
+ 45dd69f8f5aae724
+ 14054cd1f35d82760b2cd00d2f99bfa9;
+ 000102030405060708090a0b0c0d0e0f
+ bbaa99887766554433221104
+ 000102030405060708090a0b0c0d0e0f
+ 000102030405060708090a0b0c0d0e0f
+ 571d535b60b277188be5147170a9a22c
+ 3ad7a4ff3835b8c5701c1ccec8fc3358;
+ 000102030405060708090a0b0c0d0e0f
+ bbaa99887766554433221105
+ 000102030405060708090a0b0c0d0e0f
+ ""
+ ""
+ 8cf761b6902ef764462ad86498ca6b97;
+ 000102030405060708090a0b0c0d0e0f
+ bbaa99887766554433221106
+ ""
+ 000102030405060708090a0b0c0d0e0f
+ 5ce88ec2e0692706a915c00aeb8b2396
+ f40e1c743f52436bdf06d8fa1eca343d;
+ 000102030405060708090a0b0c0d0e0f
+ bbaa99887766554433221107
+ 000102030405060708090a0b0c0d0e0f1011121314151617
+ 000102030405060708090a0b0c0d0e0f1011121314151617
+ 1ca2207308c87c010756104d8840ce1952f09673a448a122
+ c92c62241051f57356d7f3c90bb0e07f;
+ 000102030405060708090a0b0c0d0e0f
+ bbaa99887766554433221108
+ 000102030405060708090a0b0c0d0e0f1011121314151617
+ ""
+ ""
+ 6dc225a071fc1b9f7c69f93b0f1e10de;
+ 000102030405060708090a0b0c0d0e0f
+ bbaa99887766554433221109
+ ""
+ 000102030405060708090a0b0c0d0e0f1011121314151617
+ 221bd0de7fa6fe993eccd769460a0af2d6cded0c395b1c3c
+ e725f32494b9f914d85c0b1eb38357ff;
+ 000102030405060708090a0b0c0d0e0f
+ bbaa9988776655443322110a
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ bd6f6c496201c69296c11efd138a467abd3c707924b964deaffc40319af5a485
+ 40fbba186c5553c68ad9f592a79a4240;
+ 000102030405060708090a0b0c0d0e0f
+ bbaa9988776655443322110b
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ ""
+ ""
+ fe80690bee8a485d11f32965bc9d2a32;
+ 000102030405060708090a0b0c0d0e0f
+ bbaa9988776655443322110c
+ ""
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+ 2942bfc773bda23cabc6acfd9bfd5835bd300f0973792ef46040c53f1432bcdf
+ b5e1dde3bc18a5f840b52e653444d5df;
+ 000102030405060708090a0b0c0d0e0f
+ bbaa9988776655443322110d
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324252627
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324252627
+ d5ca91748410c1751ff8a2f618255b68a0a12e093ff454606e59f9c1d0ddc54b65e8628e568bad7a
+ ed07ba06a4a69483a7035490c5769e60;
+ 000102030405060708090a0b0c0d0e0f
+ bbaa9988776655443322110e
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324252627
+ ""
+ ""
+ c5cd9d1850c141e358649994ee701b68;
+ 000102030405060708090a0b0c0d0e0f
+ bbaa9988776655443322110f
+ ""
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324252627
+ 4412923493c57d5de0d700f753cce0d1d2d95060122e9f15a5ddbfc5787e50b5cc55ee507bcb084e
+ 479ad363ac366b95a98ca5f3000b1479;
+
+ 0f0e0d0c0b0a09080706050403020100
+ bbaa9988776655443322110d
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324252627
+ 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f2021222324252627
+ 1792a4e31e0755fb03e31b22116e6c2ddf9efd6e33d536f1a0124b0a55bae884ed93481529c76b6a
+ d0c515f4d1cdd4fdac4f02aa;
+
+ ## More tests, made with the toy Python implementation.
+ 60d7bcda163547d348b7551195e77022
+ 907dd1dff7dac5c9941d26d0c6eb
+ ""
+ ""
+ ""
+ 7d2702e740fddada3e57a788402f9d44;
+ 14ad568f86edd1dc9268eeee533285a6
+ ed810c9b689daaa9060d2d4b6003
+ 06
+ ""
+ ""
+ c129582b8bd54dd2e80592f467112495;
+ 2365b0a54364c76c160f11896c479484
+ 6ecfa14a7130c9f137120634c951
+ ""
+ 98
+ 8e
+ 27a9a3f75d1f36a156c714d820d0b3ed;
+ 48a877ff77bf79192a5b50ade5d9cd73
+ 9a3d1f337f29549e6b0d27
+ ""
+ a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e60
+ fb544221d7bde1ec31564a9580440c902d76a7df1eff12955d17995e9bfe2336d4c2eeb42a6656dd37200ce5ff9cabfe
+ 0f9ff860aba97bfab2845af16558883f;
+ 57acc87638f508046733d9ff61cdbda3
+ b3e9878731ebfedd4705e505da
+ 1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa4
+ 50727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54ef
+ 08584d252daf79311ca8d694e33e04711f723c890a222e7ce75ff2842e87e39d714934e8c6dc3640ffc5cdad1634063c
+ 679f104fe67c507aec33a0e15b589bc2;
+ c9a38378c5b93bf4f2aad2605faee2b0
+ 3fb648e27fff63102758fe2b69ac
+ ""
+ 26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b
+ 63c2bf2254c696b288b0f41fb5b44bdf45914dce25d0071438069dbff337bc844506e5a47a28c700500280c08c54a5e4b43118ce36
+ b9fde958caee8ea9cdbe8425ddb382ad;
+ 571ea629c54d57dd2d42f70800df9fcb
+ aca48b77dba189196d1ebba10b04
+ 67cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a2226
+ 0c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b
+ a459d6659d827b523dabbc0a66cf8c151764b24a59199a6d8e4a161ace110c683dee759f823be08f0538fce282d036d2c7653ecb91
+ 63bec719103775440457715faa831368;
+ 5337685a96ed65b9aca338527ef19b09c063c46f
+ 88de9fd41e72d7b97e23e6eabdff
+ ""
+ ""
+ ""
+ cc2b3f40254925c2e221259c3b6e8df2;
+ 3bcd211499268878dbf30f1dad89d4b9b12012e4
+ 713df46795630e7952d22bb02d71
+ 00
+ ""
+ ""
+ 272e89e7297e08da41d775d62b336e80;
+ b8b649377d20a8f083455b663e4ee1315f3c8f2a
+ ebfa921451dcd1af5813b70d30ce
+ ""
+ 2f
+ cd
+ 3c1a46e21f59810999d3ef51f0460322;
+ 1fef6ef315d0798391805da08da3aefc5f8584b7
+ c5e617669c0f16e39815d4
+ ""
+ e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69
+ b75d269e9b2a080fd4d34bf0f8e7007e289b3f84ae1b8b6635fe27c5121605f12ab038a2fdfe7e29128beb944fe01b4f
+ 0e98f9a81eb34cde7f67bf40e05b6058;
+ a4cd52147ed12ca986981a874498ad0abef8bc4f
+ cb70e27e98ef1f0446b42fb144
+ d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00
+ 456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6
+ a4b540f15bcf54450c71860ffb180accc2b9218e4780a80b11cda67f1c38c8a9a8b0c5d42b243c5007b1832868dc1212
+ 9fdcf861176e933b53461b27aa00e837;
+ daa089c3f9099c5ffb824173d7634c04226f30cb
+ b7f0e4a973a8cd190107314717a7
+ ""
+ 7456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0c
+ 9897c9d1b74b1f19e984b37cfb2823670e662d5b26bc7216a174fe2bdc87b7ae8e76f57b71cf8ef83d9f7da96a5f470d6b29b62f06
+ cf1f7c7135e2f593a2b66800fbf07ee8;
+ ae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f
+ 0911e32d65cc1770a18cbfe6effd
+ 1ff6778554acf1270485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b480aa3a4c84cef64f6c9b5
+ 3bf8f957f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac8451
+ 7df3a815613704e6db80308c5e5161430a724f4a11dee60f9b0519f96f29c8c6fcf91443f230d7ee8fd8206e0c71161e9d770d5586
+ e54a174b4a61d1ee1faffa2dd7a59f70;
+ 399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65ba
+ d397abfaf529ee41cf9a05c7efed
+ ""
+ ""
+ ""
+ 74e3172048a0aed02ad958e79920884b;
+ ef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e
+ 8a5718fd25014107c8e7d715a92a
+ dd
+ ""
+ ""
+ 148ca2d47df2264f1aba1b2b374aad1a;
+ 9589d1f5c054b2d983514605ec590294a319b9802068a9f891bc5ba5
+ afabf8c3122d12d7ff3c41122d70
+ ""
+ d1
+ f5
+ 4c185af3fa049730ff516d35fbda064d;
+ 7d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7e
+ a2725cb2dac07ecde95759
+ ""
+ ac46fee6dda7abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4563d
+ 64e99a93b20ce72c4e9da3b335e722e85aeb922ace51720c32f4edb402571244d7d1e4f3d2bae1baa06da5ec6d7368ec
+ bd4509f46b03609bd11124376731fa19;
+ 405e51881e99027b8ab9aea3ccf860b0009740763d96836c5f87b954
+ 60938de1288c69d80ea12ff4bb
+ 5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c36800d9645563a308ba600
+ 76817523bd2abf1261b089d8f23a9c2835076a23faac2cdd67771cc667a8331f0a170b66283e4f834a06148f302c3973
+ ede69717cc474d94579f3aa442ecb523504280aa8dfb5604e81f8f18c5aee67140400e27ee7aa624cc3d2f8bd8eb1dc8
+ e3472e0b88ee37919d72e8a29553274d;
+ accd56f6f24e33958b8c2e2352fd61e4fa8fec816ac861a8b33779f0
+ 9e7a10fc02a8f48afa3080ee119a
+ ""
+ 52a9a817e4f2b94b0820cab383a8cffeea7c486315799dc875fba578c8ec4837898a92142b5b0677da1ac273117b45bcfff5d5f8b6
+ 6ea42fed3a9e40ae5bd32e3513e027f791595675af5e77e0044070af2ce0ca4e1facf77f6b7f0c16b2c3c528343a9c7c6d1352517e
+ 476ce6884dfa2a97ce67aafcc3375ea6;
+ fde2893232a9f81d14517ffae475f6b94a43a67b3d380d2f9aaafe2d
+ d721c0095c8808847689211450ba
+ 8095ffab1eaadf66fd22ac1976063e113ab61f813e28a1397a7974a1d7f4220c785fe426a5a0e80f678d40
+ 4147842941feeffdc2eb44dc8c0d5e8f444f7f4e0c893959b74dc23a7bb40e7e0013e5150686d2301b43a15a84e81d7f5cedaa49e2
+ 17fa00469b04d4b9563e87be4bd5f9cffd0238adb9ee98938dabb0528e0fa95fc3cf499e67d4d19606242736d8e776bd5357a0d48c
+ c8ef4f4fccad46f7fb55786818991586;
+ 414ebf47970e560475cff206
+ 877de69146acc3ab6cf8556b7aa7
+ ""
+ ""
+ ""
+ 17c75f5f7d6d099a7d375b9ea6ee9fc6;
+ 76945948d1b8834df2196c92
+ ec1718dcdeee0d52d9539726d281
+ 03
+ ""
+ ""
+ 2abbc7c4cac1b870f9e8a92f00f1f2f9;
+ 91b3f9d10c39b07ae8f08ce7
+ cee4758a386a9943e97dedfbe61e
+ ""
+ 73
+ f4
+ 8ab448b5400b1a46c7c5e20ef9700e22;
+ 7882cd09c2b9a80f34c0fde1
+ 1c2481b11fc76bfa4dbf71
+ ""
+ 0a9e544e0c536ca1e040f9ad5b04140d98edabe08485290a4d87d13b07398a1458c2c6b61dbdbc1cccada8c1a0a9aabb
+ 7c8660ca8ca219cd98abe715c166df757edad193c7d1a6f9227d7633b1666bd34c86f6df7819a80903e5c37ffc5e0648
+ 27c846118776e3626f15532888d3f887;
+ 6c4e3c3554f8fb1ef61614c2
+ 70295dfc0ca6551ca4bdb75359
+ f91cb9d921056b7de74fc9a9b37154ce6c0b396179d31f06a1dd5982cbc0d7cb23841da1ae8f4ae480cda98ad6cf2bac
+ f6f9fd3f821330c43f3df6c2b3fac7cbcf96523d4723f91801325eb8553236651c96788d73d192ee53b3f3ebd66ddd98
+ 9c912ef9d07d26881c823aecb92e81cc988fbdd1292d49ae9cddc5c1fa5e1a618c96e71c64866481926bc83c1c2ec172
+ b7f45c7b104609fc3be061ebb388ee13;
+ cedbe88e245de25b1593b70f
+ 8601562d90a9b59ed034a867642d
+ ""
+ 25d54756fa5c47f16f64b837bb4926214211a1c696ba172010abb433922a22d9fd881519165eb9d85197a21cc34ac0d5ae7be8dbf9
+ 00bfa16e1410e13d46752a90f40b6d9f6193cf06930ecb55abd2f973b710fa0582b30f87e5edc850a652def300f06da79231471399
+ b8858413846d2de7fa4654376b1b9f1f;
+ 8e4ffed2cf6b1372a5aa47b5
+ 4fd9d70c70e117bf1cae71b3a56f
+ 0e7d839ea59cc783443d64f2ed6a29b96856beca34fd6544bcf86b799e2a1681160ccf055f0fd3001da597
+ a1406d465b7b1419ea51cf858f938f6daafbd656445a09898eaa96ffc3d1d2e31e4e34c94b8bfae64825ecd75a66d88eedb969ffe0
+ 9cadbe9441f1705005b73f4e5b1675fc77390306e768a3f599a8fb11846ec535f0fa52e88120d3409912c342401b16a395784c6dcc
+ 44773033baea19b7a13cfe0f67d9da85;
+}
+
+rijndael-ocb3-mct {
+ 32 d90eb8e9c977c88b79dd793d7ffa161c;
+ 28 a3c8ceaa94b405effc970e05f15fa2ff;
+ 24 f673f2c3e7174aae7bae986ca9f29e17;
+ 20 c8bc484858c5b1bc9e4241e2f552b371;
+ 16 67e944d23256c5e0b6c61fa22fdf1ea2;
+ 12 2e9806312d331fe78476fe88afb74763;
+ 8 2cfce691258f4d0300c220a6ef4d0a81;
+ 4 5d36742a2f065dc845789585f81f052f;
+ 32 5458359ac23b0cba9e6330dd;
+ 28 a14417b0bad703c8d1eccd2e;
+ 24 05d56ead2752c86be6932c5e;
+ 20 a61001205f451947258a950d;
+ 16 77a3d8e73589158d25d01209;
+ 12 6a32e20692f16b31a51cff6d;
+ 8 211b29176d56d0528fd70c9f;
+ 4 db638b2ddc074fe1ec1056d3;
+ 32 7d4ea5d445501cbe;
+ 28 94d6f38a6bcf4fa0;
+ 24 0066bc6e0ef34e24;
+ 20 1a583bc011e8a4fc;
+ 16 192c9b7bd90ba06a;
+ 12 385bcd58e8387991;
+ 8 2fb22e566436473d;
+ 4 c00b55e9a2bed310;
+}
df6e46c2dbf69f357bbe22bf604efca58a7352a18f41a7ad
1d5fa8d85dc2428dabb69eb4c9cea7180f2fa554eadb9dc4;
}
+
+rijndael192-cmac {
+ 60d7bcda163547d348b7551195e77022
+ ""
+ 60b69a71abf68553087a4635c8f3d6a6445330a424fcd5bc;
+ 907dd1dff7dac5c9941d26d0c6eb14ad
+ 56
+ a70f592cc5ea00d17b15fa9810fd694c21e9df121ef3b4b4;
+ 8f86edd1dc9268eeee533285a6ed810c
+ 9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba
+ 872bf13b5f881a915c9342329f04911369c818c0ea171840;
+ 234085406a6136512061f7080cc07df0
+ 591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49
+ 8b456186aa6c2a0d7595f606dc18e4934435f659d05d8994;
+ ae1d50c38201a894476b3f102b752eb952953396
+ ""
+ 2d401a31a7641d7793074c1fd8f49be54d4b542aaefaa85b;
+ 6f27043eb621b7f65b000961040ef2f9b2fc5fa4
+ 50
+ f6433b85e1c5134170efabaf9787fbd7e65cb12ce129d440;
+ 727a9b542cde52ebfda19d0ccc520f215eb57bb3
+ a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f
+ 20c4e9333e614096c96a21d83ef6779616d99f93167fd455;
+ 8f28523c03d4de1600157846b710ee72807a2219
+ bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f7682
+ a7ae91664738b763e5d45d556edd0b59923f159dc9cea08f;
+ 81e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a
+ ""
+ 558b741080d1a886fd8798f4100853f2004201a48be08907;
+ 42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c
+ 03
+ e115710b82135a9cbc43aefae273556dcfb62394c78417a6;
+ 7ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9
+ aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f083455b
+ 22ac79b7ae3011dc8a14b3516edadac8de849d9599fefa6c;
+ 663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef3
+ 15d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e4
+ 57c8bb706e09c6ac44146a999925abef54403c8e610efca4;
+ 7479a684b5aefa69a4cd5214
+ ""
+ afde241e1a29decdd2f924776073a7108b90a02528d9db4a;
+ 7ed12ca986981a874498ad0a
+ be
+ 37beddab340f4b5245afc8b5a0fd78004ffcdbdd2f3a41e5;
+ f8bc4fcb70e27e98ef1f0446
+ b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc3990844
+ 4d27aa546ff3594eeaf076a140cf3e38686d4d9b2d9f75b5;
+ 5608fe95e81c2533e31c9c1a
+ 9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e
+ 3848a7fc35a38ec5c202692eb9cc03067f1e3a587996a2fe;
+}
+
+rijndael192-ccm {
+ 60d7bcda163547d348b7551195e77022
+ 907dd1dff7dac5c9941d26d0c6eb14ad568f86
+ ""
+ ""
+ ""
+ eb328a4c;
+ edd1dc9268eeee533285a6ed810c9b68
+ 9daaa9060d2d4b6003062365b0a54364c76c16
+ 0f
+ ""
+ ""
+ b2ac3bb1;
+ 11896c4794846ecfa14a7130c9f13712
+ 0634c9519848a877ff77bf79192a5b50ade5d9
+ ""
+ cd
+ d3
+ 2fe24f74;
+ 739a3d1f337f29549e6b0d27a4ba2340
+ 85406a6136512061f7080cc07d
+ f0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c3
+ 8201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c
+ 6d7e47a271f0a9140ab83f9874698af802509e3ce08ae633274ec72ba7fc0439a766245ae5ea7e1581432240c5e9400e5d4da1d9f3ab8d203cf35bbc9bdc48354be9ab81d3c97197
+ fa0923d87206b84258099d69261e1f86f7da4740051c5087;
+ 33d090c54215abd6b3ad54efc9a38378
+ c5b93bf4f2aad2605faee2b03f
+ b648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b57
+ 1ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42
+ 3fc60a985fd9a0b75ff268e4dbf8c87195dcd97029ed59b6a8592fac9a954fd250025e1cb3fb3c7d509e327ceedf08d3c90467a66f23c7a45369ce96c0450e44b09434979c7962c4485c2b2bbf
+ 54ae41dbd56b7171107397fa7f4aa3a81f889a179161bcee;
+ bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f
+ 5fe8368131115c037ba323fe1dc8151784873f
+ ""
+ ""
+ ""
+ b65bbb04;
+ 0eb5b647da6794c18b5337685a96ed65b9aca338
+ 527ef19b09c063c46f88de9fd41e72d7b97e23
+ e6
+ ""
+ ""
+ d1f9ef31;
+ eabdff3bcd211499268878dbf30f1dad89d4b9b1
+ 2012e4713df46795630e7952d22bb02d7100b8
+ ""
+ b6
+ f8
+ 3b797ce2;
+ 49377d20a8f083455b663e4ee1315f3c8f2aebfa
+ 921451dcd1af5813b70d30ce2f
+ 1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e474
+ 79a684b5aefa69a4cd52147ed12ca986981a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720
+ 7b80a5b2f5259f81e3e755ac7afcaf2dfc39714c0b17a69c8a126fcf854ce88936114c5309af3ebc4d06437399884d56edcd0d5d89c0106326b3f801ac391c6ecfd167efc7d1b7d7
+ 4b5a71ab534a4ae72dd6709be87c69173467728ed407de1f;
+ eef9eb1c8dd0b00951f284649016ed0045633185
+ 4bc78bf43966eb0cfa9138ddc3
+ 9908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456
+ f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc
+ 24d3d61a7ec5951c8e7687bf216082e306d71c7a9351d45e7272418a2e4a22c8d5f5255abc0f1f081919b0910596727bc3ac57f0f4e55d562144ea20ccac5c640ea08baf53f71e35faaa8d75f0
+ 65337469537455c0488f31bdad41f2bd174c2b890dad1d33;
+ 1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967c0a458
+ cb948bdd409b687fa3a6827b480aa3a4c84cef
+ ""
+ ""
+ ""
+ 773f8182;
+ 64f6c9b53bf8f957f4b03cf43e89957f9a3e8128f8743d16687b7bb8
+ deb9bd205b70e04c091d205cdad9e9a79b1abf
+ 91
+ ""
+ ""
+ 1bad4133;
+ b0851e5ca605ac8451399587011677508a15dde524af3e2bee064654
+ 1a42c2ecccb44d65bad397abfaf529ee41cf9a
+ ""
+ 05
+ 41
+ fdcd5753;
+ c7efedef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213
+ e33f7e8a5718fd25014107c8e7
+ d715a92add9589d1f5c054b2d983514605ec590294a319b9802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6
+ 699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4563d405e51881e99027b8a
+ 7f1ac5936bacdff5ab2339c74028aedc3266926aaa6685e9b688b5ac499d1a6912f4c957dbad07dc747ea4b9855f7656fd6952cbddb4a0296cf2e58227e0c05fad7d373f3a6a081f
+ bc33380a30663863f7d96afb80b51b7e89b08bbe5d523f62;
+ b9aea3ccf860b0009740763d96836c5f87b95460938de1288c69d80e
+ a12ff4bb5f069b8a2e86041c1b
+ 9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c36800d9645563a308ba60076817523bd2abf1261b089d8f23a9c2835076a23faac2cdd67771cc6
+ 67a8331f0a170b66283e4f834a06148f302c3973accd56f6f24e33958b8c2e2352fd61e4fa8fec816ac861a8b33779f09e7a10fc02a8f48afa3080ee119a52a9a817e4f2b94b0820cab383a8cf
+ 055eaaabcac3b8d64c9d744eb534ea4259d6c114554cf28dee96aa729da5b70556f4a9a8724506b42fe6b2d266db7cd0b904881f7dcd312ea17e9d256e14fc40d8d6a6286cbcc3772cb3c79f25
+ 72c96466655bf5d891fab5d415bc6065d3902ca0b8f95a40;
+ feea7c486315799dc875fba5
+ 78c8ec4837898a92142b5b0677da1ac273117b
+ ""
+ ""
+ ""
+ bcaf4c92;
+ 45bcfff5d5f8b6fde2893232
+ a9f81d14517ffae475f6b94a43a67b3d380d2f
+ 9a
+ ""
+ ""
+ 25f9961e;
+ aafe2dd721c0095c88088476
+ 89211450ba8095ffab1eaadf66fd22ac197606
+ ""
+ 3e
+ 10
+ e0be6bf8;
+ 113ab61f813e28a1397a7974
+ a1d7f4220c785fe426a5a0e80f
+ 678d404147842941feeffdc2eb44dc8c0d5e8f444f7f4e0c893959b74dc23a7bb40e7e0013e5150686d2301b43a15a84e81d7f5cedaa49e2414ebf47970e560475cff206877de691
+ 46acc3ab6cf8556b7aa776945948d1b8834df2196c92ec1718dcdeee0d52d9539726d2810391b3f9d10c39b07ae8f08ce7cee4758a386a9943e97dedfbe61e737882cd09c2b9a80f
+ 633bd657368c964b774d76c9a8deef5e79c2db8c3ba300ff01b9a1685cb5688f8477c50bf62f380d5dcbf7e9fef05b73415e446f8675dcbd02c9a182b3647d7fc7e5320b9fc480bb
+ f3a1b675f8b96ce151ef507f6a587f4f9d78db3df352eef2;
+ 34c0fde11c2481b11fc76bfa
+ 4dbf710a9e544e0c536ca1e040
+ f9ad5b04140d98edabe08485290a4d87d13b07398a1458c2c6b61dbdbc1cccada8c1a0a9aabb6c4e3c3554f8fb1ef61614c270295dfc0ca6551ca4bdb75359f91cb9d9
+ 21056b7de74fc9a9b37154ce6c0b396179d31f06a1dd5982cbc0d7cb23841da1ae8f4ae480cda98ad6cf2bacf6f9fd3f821330c43f3df6c2b3fac7cbcf96523d4723f91801325eb8553236651c
+ 77d68b7c74c11fa6f23cab03c8e20965e7362191f15a359371f06954d0a8673d43d291db49563e5775d590a5b66a4de2c79fa96da0bbe7b18ff98fadead8cdc6bf8f559ed3675d46cca4cb27f3
+ 828d1b75c068055451d00b6a0e8a5b0e5672f780c282a170;
+}
+
+rijndael192-eax {
+ 60d7bcda163547d348b7551195e77022
+ ""
+ ""
+ ""
+ ""
+ 4f06617fd2435935d07da73b3fa4147dac1325a119046009;
+ 907dd1dff7dac5c9941d26d0c6eb14ad
+ 56
+ ""
+ ""
+ ""
+ 91538eab427977388accbffddc6478f21b5fecbc6c7cb90a;
+ 8f86edd1dc9268eeee533285a6ed810c
+ ""
+ 9b
+ ""
+ ""
+ e5c24c4b113407583e10b409e553d653a5a519cba5f6d500;
+ 689daaa9060d2d4b6003062365b0a543
+ ""
+ ""
+ 64
+ b2
+ 04d4d6804877ab6f6b3fa8566da51a683626144b1f15b0c9;
+ c76c160f11896c4794846ecfa14a7130
+ c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd
+ 739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff
+ 61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde
+ 5ab0c81553820168ce731c21e2d27c369cee4e9e62ad20e90f838e1e625efa976022de1063b1eea5f4b80f436fa05ff63b8805ccffe979d6d3809360b85598694b0e56f834aa44d6
+ 4808e60011165622ccfea271b2720944612f7ba9fdaeff2b;
+ 52ebfda19d0ccc520f215eb57bb3a4f3
+ ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad
+ 54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219
+ bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689a
+ f741602c2f1d8e46421651f6022a8c5525619a3231ccc623aa9220867f029b7fb8ded5cf9ecd06524d68399fad71cff1f9e3ec8b384d0eaa143f69593400261ad9bcb746d9be5dd613118b6448
+ bb31af3207c2cabea82345be05be7fdf5198225ca65e71ed;
+ ef66f5306ceb0c6b08ac8b0a22260c571b4a42bb
+ ""
+ ""
+ ""
+ ""
+ 9f2973f4e855065a8d48db995fb178a141518b2737ac40d3;
+ 8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5f
+ e8
+ ""
+ ""
+ ""
+ 44295827bbc06d0fd366f80689343bff188759f2cd39683c;
+ 368131115c037ba323fe1dc8151784873f0eb5b6
+ ""
+ 47
+ ""
+ ""
+ bc4ca9743e53d5cc9fae593892c0ce36d6a7d08547cfe2ed;
+ da6794c18b5337685a96ed65b9aca338527ef19b
+ ""
+ ""
+ 09
+ 7c
+ dec701d10c4fdb386ca3d6546339bc1f896eaf2ab62fcc63;
+ c063c46f88de9fd41e72d7b97e23e6eabdff3bcd
+ 211499268878dbf30f1dad89d4b9b12012e4713df4679563
+ 0e7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e3
+ 9815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a874498ad0abef8bc4fcb
+ 0d0020cb99818864e1a42510c9f02fa9d8e1b7eeece9e2a47aee82a256d573aa3b4fc5e71b7bb3c728e738eb84efe398a767378611a9c567ddd1f2d1dde0542273f61eb745d20483
+ 2370d3c0afd70bc36b3bf48b066e6a669bb6421d7c96f5a3;
+ 70e27e98ef1f0446b42fb144d44b6d00f06dc188
+ d472a784e0c6f21195a3b9f4ae985511265febd11c1647
+ 20eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa0
+ 89c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0
+ 8c2e22689dfa878356ce69e873da970dfdacb405aab70851448ceb62ba02cb110d425683508f8575dda4f95545df5db12e04bffcf5b81c5b83a4ba6e5dffa6421f513791b59152f2e102afefe2
+ 3e1b8d85bd6ac24ef82725ef0240e33f237223e26aff80ee;
+ 945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f
+ ""
+ ""
+ ""
+ ""
+ 75e5558c9504d6207f55489f4884c98abb6e0beec7a95435;
+ 0911e32d65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1
+ c4
+ ""
+ ""
+ ""
+ e39471f2d0b80ffcb2dbd929c96ae456486b7d8b3f11876e;
+ c967c0a458cb948bdd409b687fa3a6827b480aa3a4c84cef64f6c9b5
+ ""
+ 3b
+ ""
+ ""
+ 6b3580a5ea32ba95c99712d167ca737628592fea8e2e2b99;
+ f8f957f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd205b
+ ""
+ ""
+ 70
+ 01
+ 124d761a70529ba540c4a3fdc8f027dbb1795a730ad5e11a;
+ e04c091d205cdad9e9a79b1abf91b0851e5ca605ac84513995870116
+ 77508a15dde524af3e2bee0646541a42c2ecccb44d65bad3
+ 97abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a5718fd25014107c8e7d715a92add9589d1f5c054b2d983514605ec590294
+ a319b9802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7
+ 9f006d1fa01a0740b164f5e4c14a110cf20206a44206cd847498c555a495fb07fbb62f35082ec3303cc08298c364656b41c741318162786b2fe494e6cde8b670e64ef492de01027f
+ 712accd8ada4c4492c6fa2357c801ea07cb16b55179e2a5d;
+ abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44bb
+ c8c6254d980398bd94e66eb4563d405e51881e99027b8a
+ b9aea3ccf860b0009740763d96836c5f87b95460938de1288c69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ff
+ aa6c36800d9645563a308ba60076817523bd2abf1261b089d8f23a9c2835076a23faac2cdd67771cc667a8331f0a170b66283e4f834a06148f302c3973accd56f6f24e33958b8c2e2352fd61e4
+ 7a12401a5a74a3791b3fea7958393230536885a7761e3716e36c2b571bf9510dc268dd30a4faded0794addc797a0661b6d485a4ed2c50ecefd4932e615ab6cc4c9180bcd5491541475508f873d
+ 22a1b541c2b7a784bcaaf00680273feb1a93c187e601413a;
+ fa8fec816ac861a8b33779f0
+ ""
+ ""
+ ""
+ ""
+ e78606fd15a8ba1222d2f85ece0d3a66618ad8308820fdc9;
+ 9e7a10fc02a8f48afa3080ee
+ 11
+ ""
+ ""
+ ""
+ 2a1684ea67082c34418df0f0d2366cfc1080b493930feaec;
+ 9a52a9a817e4f2b94b0820ca
+ ""
+ b3
+ ""
+ ""
+ 83c2f7ecef5d874db22c51272440484a8fcd0b3beb84761c;
+ 83a8cffeea7c486315799dc8
+ ""
+ ""
+ 75
+ 1c
+ 1d96631473b4223491a78b3e90f91223dff32d90811433d3;
+ fba578c8ec4837898a92142b
+ 5b0677da1ac273117b45bcfff5d5f8b6fde2893232a9f81d
+ 14517ffae475f6b94a43a67b3d380d2f9aaafe2dd721c0095c8808847689211450ba8095ffab1eaadf66fd22ac1976063e113ab61f813e28a1397a7974a1d7f4220c785fe426a5a0
+ e80f678d404147842941feeffdc2eb44dc8c0d5e8f444f7f4e0c893959b74dc23a7bb40e7e0013e5150686d2301b43a15a84e81d7f5cedaa49e2414ebf47970e560475cff206877d
+ 7daf1f5c982d561f22d520d3a528bdc16ea98a48c641b6314b0cd5c6da05f6bc6f3519be0a2c81177e44de266afa4f62b72d9c2800c039115ab81b671d940e314f1edaabe7685aec
+ e7d163d20f75659b4b0fa2b150abfabd0e1a83a4d5903a20;
+ e69146acc3ab6cf8556b7aa7
+ 76945948d1b8834df2196c92ec1718dcdeee0d52d95397
+ 26d2810391b3f9d10c39b07ae8f08ce7cee4758a386a9943e97dedfbe61e737882cd09c2b9a80f34c0fde11c2481b11fc76bfa4dbf710a9e544e0c536ca1e040f9ad5b
+ 04140d98edabe08485290a4d87d13b07398a1458c2c6b61dbdbc1cccada8c1a0a9aabb6c4e3c3554f8fb1ef61614c270295dfc0ca6551ca4bdb75359f91cb9d921056b7de74fc9a9b37154ce6c
+ f2a5115aa965c209277a24b0c325ce806520f4725aba623a5edd757c9b8ae4da2f4e918ceb2ba756bea2b7e16ce28cd808151ff29ea78c662ddaf739313c5930e2859da808369301b81db91309
+ 77613f8246951823e51a3370da0344a58531540bafeded71;
+}
+
+rijndael192-gcm {
+ 60d7bcda163547d348b7551195e77022
+ ""
+ ""
+ ""
+ ""
+ 015da0e6189d029fc8dafe862408dcabc30fda92fc68e1ad;
+ 907dd1dff7dac5c9941d26d0c6eb14ad
+ 56
+ ""
+ ""
+ ""
+ c932ffe01a259789c15ce089d5f8b7ea68f802ad4f95d278;
+ 8f86edd1dc9268eeee533285a6ed810c
+ ""
+ 9b
+ ""
+ ""
+ f00e7ec01693132f470761f98c38f8059d68abf0f24619cc;
+ 689daaa9060d2d4b6003062365b0a543
+ ""
+ ""
+ 64
+ 10
+ fe5372d9b2db602ba2611ebc0100bce5c00bbed04792cb05;
+ c76c160f11896c4794846ecfa14a7130
+ c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd
+ 739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff
+ 61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde
+ c59a7b60e5c4237f3c10e9cde0219aa4099ef7c0323b9b6a2b9c403327510e8966c95884af2892e93562b24c97711b08dcd6d3f96cd6ef4a4965ea599ce6483cc8cc7b356ed79aa4
+ 5ce6dffcc1adf4308013c22d19323d83025c0f821b25bf4e;
+ 52ebfda19d0ccc520f215eb57bb3a4f3
+ ebbbb18ac6c95a97a48030370c33d090c54215ab
+ d6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff
+ 63102758fe2b69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77
+ c82c8f3a0ce6dcaefdb53e2e831e9192559ce8c45c1967f5a9ef2f3ec68b94c9c2206a606c318d53ffe10e195a5d3ad88a866976d18550e9e13e6d3df6954b675eda0b433bc4bf78a46eb25038c4c1e1a6
+ e2203c3246cd4609749431f291149ec7359c6c1f98316738;
+ dba189196d1ebba10b0467cb9fc2712a
+ 199e533fa9156308cdec3f768281e040a9b9a222bd689a
+ ef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b
+ 5337685a96ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f0
+ e4e1aa2a9dc0ecadfab0d06a51cc52bc051eece169d640ea09e5ecbc5132389d823bf160bc0c3fd935be0a07b7350bf34aae3a6e93aa874aa8df85949f3ffce3ad63b63d972067f2ffb42da610
+ 033ee0ffd59a68e6c64bcf376e1b4b5c3b55b704af3efd30;
+ 83455b663e4ee1315f3c8f2aebfa921451dcd1af
+ ""
+ ""
+ ""
+ ""
+ 11162ce42451687d06c7ea1d05f235a12f8c1dec59f7ffb9;
+ 5813b70d30ce2f1fef6ef315d0798391805da08d
+ a3
+ ""
+ ""
+ ""
+ c9f80fcab02986639b9e1f4240582daf41b51a065bc6638b;
+ aefc5f8584b7c5e617669c0f16e39815d4e9cfce
+ ""
+ 3e
+ ""
+ ""
+ 64f584488df21b4e6a7cb5b54551516ed0585564f2605551;
+ d1ecdf3d264a7f16cb16c2e815f422cdf0c8e303
+ ""
+ ""
+ 08
+ 93
+ 9dd3171ccac6312ff23949e0145b1f20c157eb70c7a100cf;
+ be3c31e6bc58c0b7cadcb658b970e47479a684b5
+ aefa69a4cd52147ed12ca986981a874498ad0abef8bc4fcb
+ 70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0c
+ fa9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456
+ 2aa894b96eb2a06a0c601e1f32a5495741e7cd0d98ade2e22742931a96e86b1620f6bf3dc60e865f24029760aaac639a9628575a224c48cabb0b207a8c646da177f0180a9484003b
+ 09e91a6ca2951ac43b2dc376bfb2459f9d6793f3fa6f19b0;
+ f3ff669c732b58db8f48af65f7cc9e3fb90e1721
+ b730374ffc9bc597f56ccbb2f294b38766fc69f6
+ a9f2c0945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a125
+ 8b2b9b8f0911e32d65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a3e8128f8743d16
+ 2a34e82df940e666655df615cd9499c3f0cbcb42d214c38a86130abd270c3f2a1aeb290e30d3aa4ff7e5386ebe20a7140c329e02f8e79ae908e55b44b32201191c1061d525d815983d8a413460155e66a4
+ 62d2e5ef4662b6a369d06431d0b42ad0e89280500ba3eba1;
+ 687b7bb8deb9bd205b70e04c091d205cdad9e9a7
+ 9b1abf91b0851e5ca605ac8451399587011677508a15dd
+ e524af3e2bee0646541a42c2ecccb44d65bad397abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a5718fd250141
+ 07c8e7d715a92add9589d1f5c054b2d983514605ec590294a319b9802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e
+ a5d9d4f2cfeaa5003728d73631498986caf5ecd07f21be526aaf0ba42f4e94ea4601b93fd94d3cba101bfd9f4092d31c37a787d481bcf6e0327ec520952a55bae4cfdff57b0b5aae071e182b89
+ bff9d687d796f186e930b3d45a7ef9da7cb6309fece26936;
+ 6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68daac90cfe2
+ ""
+ ""
+ ""
+ ""
+ 20e8e27fd32514b1b14272c20f0df7247f31f1f4a12f25fc;
+ 2d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94
+ e6
+ ""
+ ""
+ ""
+ ada7ffde4179f00a0efa887dc253ca41f00c318ed87aa2ee;
+ 6eb4563d405e51881e99027b8ab9aea3ccf860b0009740763d96836c
+ ""
+ 5f
+ ""
+ ""
+ 378e18a38eba655e06b6f1e4d453e0afbdecb51191f33822;
+ 87b95460938de1288c69d80ea12ff4bb5f069b8a2e86041c1b9fc214
+ ""
+ ""
+ e9
+ 7e
+ ab0bb740c0dc8e10d72db5f5d9340a7f3f58205422105151;
+ ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c36800d96
+ 45563a308ba60076817523bd2abf1261b089d8f23a9c2835
+ 076a23faac2cdd67771cc667a8331f0a170b66283e4f834a06148f302c3973accd56f6f24e33958b8c2e2352fd61e4fa8fec816ac861a8b33779f09e7a10fc02a8f48afa3080ee11
+ 9a52a9a817e4f2b94b0820cab383a8cffeea7c486315799dc875fba578c8ec4837898a92142b5b0677da1ac273117b45bcfff5d5f8b6fde2893232a9f81d14517ffae475f6b94a43
+ 3f01e886e13d4af838c1a081adb8940ef6f24dabe3bd968a1c256dd08fc8c2aef84f7c389d6049f553750678d40e05e73c272540a02ae22d37e3ea42b38b7b659661fda031256ac8
+ 4e5447fbd4d6ae6b948968a3944daafb7dbfb2298afa517e;
+ a67b3d380d2f9aaafe2dd721c0095c8808847689211450ba8095ffab
+ 1eaadf66fd22ac1976063e113ab61f813e28a139
+ 7a7974a1d7f4220c785fe426a5a0e80f678d404147842941feeffd
+ c2eb44dc8c0d5e8f444f7f4e0c893959b74dc23a7bb40e7e0013e5150686d2301b43a15a84e81d7f5cedaa49e2414ebf47970e560475cff206877de69146acc3ab6cf8556b7aa776945948d1b8834df219
+ 0ce0e6e23e9b00a1925b4704d89f9ddc27e6184940419c3f4755b3a268f8ca0cefd898853791b75c9dfc09f72d8e3f1e76b68a7298131a24c15670b0f29150356b1dbb8281d2168fe870d5c2b13c7d515b
+ fc65f244ef465fab581fe151522e12881796968a24ec9f9c;
+ 6c92ec1718dcdeee0d52d9539726d2810391b3f9d10c39b07ae8f08c
+ e7cee4758a386a9943e97dedfbe61e737882cd09c2b9a8
+ 0f34c0fde11c2481b11fc76bfa4dbf710a9e544e0c536ca1e040f9ad5b04140d98edabe08485290a4d87d13b07398a1458c2c6b61dbdbc1cccada8c1a0a9aabb6c4e3c
+ 3554f8fb1ef61614c270295dfc0ca6551ca4bdb75359f91cb9d921056b7de74fc9a9b37154ce6c0b396179d31f06a1dd5982cbc0d7cb23841da1ae8f4ae480cda98ad6cf2bacf6f9fd3f821330
+ c9e1cff17ba016005ee6bd63700c2d80ed5281dd7ccd14d19514e1a0ec2a2134d9bef71d92a8bb3c71c0d4622800300d21d16cd076593c492361e2a849e71f7e51d9d6fff53b61bba0e19fb25e
+ 44aa54e465e68d39194421556344aea25bdc16f0a24c0685;
+ c43f3df6c2b3fac7cbcf9652
+ ""
+ ""
+ ""
+ ""
+ ae9a5d3998de53f84bca8beed16dac8064c3ea73d0c67765;
+ 3d4723f91801325eb8553236
+ 65
+ ""
+ ""
+ ""
+ f062371cf3f7082c2e21c136112bc6dd3eb3b455a5624800;
+ 1c96788d73d192ee53b3f3eb
+ ""
+ d6
+ ""
+ ""
+ 05013633667c00adb73c6442909065b53d12eb94db18480c;
+ 6ddd98cedbe88e245de25b15
+ ""
+ ""
+ 93
+ c6
+ 78adfa0aabbe6558983554b3e73782cadcf950c21f27ee67;
+ b70f8601562d90a9b59ed034
+ a867642d25d54756fa5c47f16f64b837bb4926214211a1c6
+ 96ba172010abb433922a22d9fd881519165eb9d85197a21cc34ac0d5ae7be8dbf98e4ffed2cf6b1372a5aa47b54fd9d70c70e117bf1cae71b3a56f0e7d839ea59cc783443d64f2ed
+ 6a29b96856beca34fd6544bcf86b799e2a1681160ccf055f0fd3001da597a1406d465b7b1419ea51cf858f938f6daafbd656445a09898eaa96ffc3d1d2e31e4e34c94b8bfae64825
+ da005542936f792bc7fed255ba5d8c04b90fa64185338a24a954b79a7d05252230a1167ef6eb35d1281c1927ffab7b5c714321e03a01274c3bd3583e3ec84f7c56d60000e18242f7
+ 2ed230cfba9714d0d3d35df936ec750a695fccd25539b46b;
+ ecd75a66d88eedb969ffe076
+ 69845ebb7a24c69f13d099f47166edf54538e88f
+ bf433a7ff212085179e79771f6eee7283ab178ef2b800d7b969da0
+ 5780ffc1ba78c70dda7a4ca2a25e771702fb1901ecfc8a959cb8e75079bb018ccc8c54f31b450e88f8e9002926ad0284c738f4cb0f58a1e34c8b15ad930c1b627235a2cb84241986c251f5b70be2367f04
+ 85ed87687fca97cdf0ccfe1d4e0fbdd56e674a6ef5ebcbc4979f80e6f8ebdc85672d01db63bef05103c1327baa49d7e6e12854ce3680f52bde86c075ff5df02daf0db3e48b564a804cb3b657f982a27ff3
+ e37d522450d16ff30f15ffa74a0b894bfd33074c4ea06f44;
+ 7265264e0da72efe8995e6c9
+ 32a17eab511eddb8e4ba463c663035a6ae8a7a899e4279
+ d54d03f0e0f3e961dcfd40088d5be74088e4097efb0368c7e2f431ee6988cf2a0e9ebeb3de79c4f86c9e4fba61339d6d907eab7707ca48ff5ba1ae93d16225d469de57
+ 47bc1addf5748729720a320fe14fd29cfc59314fe2079c0a2535ded56112d6e3d33dcf7c71cd7d130323794e3da84a9df69703a9caf02d2a8f57ac71e554a6850d55882f8c7ae6994fc8528bd1
+ 0b9e340c141493f9676c99eaa36b0463639b3db40dce5e2bb48c3222a1b82595be0ae12890f61bdc22f71a07b8ad0136d395221c57e12ca7f8184d3adbf82497f5c6ac105b1545d433a9baf50f
+ b24035d9900bc75dc879617502f0f9891a2428fa9d6d472d;
+}
+
+rijndael192-ocb1 {
+ 60d7bcda163547d348b7551195e77022
+ 907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268
+ ""
+ ""
+ ""
+ 13b24e23a3819cb4d7bf3ca036241de7b3420a061b6d62d3;
+ eeee533285a6ed810c9b689daaa9060d
+ 2d4b6003062365b0a54364c76c160f11896c4794846ecfa1
+ 4a
+ ""
+ ""
+ cdea5e7be1867fe4017045e85df90d80eab16117019cb8d6;
+ 7130c9f137120634c9519848a877ff77
+ bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba
+ ""
+ 23
+ 82
+ b32646848740cec0d5c5a20e2d56c34d455d9574159fc509;
+ 4085406a6136512061f7080cc07df059
+ 1d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c926
+ ""
+ 9029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b00
+ 5f7a353fa6c23af6ae6afcd8fae5637d8ac4edb01faa216d94a8b31628140de88e741c1acd085a5e98d64f69090556f641d8f1c813fb1b3675a35aad57f6f48ebb0b7a8270df4216
+ 76df452b066d18894a564d78abd6d0c649602bc325f73595;
+ 0961040ef2f9b2fc5fa450727a9b542c
+ de52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a
+ 97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f8f28523c03d4de1600
+ 157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa91563
+ 6ed78c4004e5960f34017f9272ef3f237d5fd83076668683183dbc0b62201d1223550af95841dc4ac72f0bc0ce36f014237d026518a6b1bd0ce01e56e87bfa9c42f4651365f65b8c
+ dbfa943531e52ab36828c47f5e21fb22ea0452f0a45395ac;
+ 08cdec3f768281e040a9b9a222bd689a
+ ef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233b
+ ""
+ fa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff
+ 74751fe7898b6a9c7e28c4e3132fccaf4b9af8ceb80ceebc88672c05c49d5286724ddc6bd3dee79921cdf0a0265277d43048c588e5d707488d1dfd90808d6b74337d1e88aac9618ddf181c1653
+ dd9c6625bb9d22266087655b51efc0a2d8cb642f6c40c6d7;
+ 3bcd211499268878dbf30f1dad89d4b9
+ b12012e4713df46795630e7952d22bb02d7100b8b649377d
+ 20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ec
+ df3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b
+ bfecbe5ee869f7c5b4bcc3282963ed6dae5755c25a070c40b4d6a8dfb74670bc440d0af7abc018642d36a946d8488aaab9eabc0c7cf4ec6d2f8a9a738c131188af47d7e791c3f7e6a34d26724d
+ 5dfee1b1d0a1ebd94737ef267a755fddd2092bfd35e7a238;
+ 6d00f06dc188d472a784e0c6f21195a3b9f4ae98
+ 5511265febd11c164720eef9eb1c8dd0b00951f284649016
+ ""
+ ""
+ ""
+ 6c1ae06b473969bf8d4abf8890f91ccba11f094b316d82cf;
+ ed00456331854bc78bf43966eb0cfa9138ddc399
+ 08445608fe95e81c2533e31c9c1a9851bc2810d858cbbc84
+ 24
+ ""
+ ""
+ 7025cfe14177506ac341239746234c80533c6fac1b94afd8;
+ d126b807e6daa089c3f9099c5ffb824173d7634c
+ 04226f30cbb7f0e4a973a8cd190107314717a77456f3ff66
+ ""
+ 9c
+ f2
+ 91c9a9506104ca20249008a5210a18e972aa0865d8c083c7;
+ 732b58db8f48af65f7cc9e3fb90e1721b730374f
+ fc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd5050
+ ""
+ 03cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b480aa3
+ 5c8a44ab82a0c2efc66e6e039e7c70a611991b5901b7578c55f4716fb7bd37f55c4bdc962f7f1ed93e14804b4d41695d639b3b5b1725c9129a47ae9542d11787064051cffca20611
+ acb050737b017b0b4c10a120a4d740a2ef33d5e26e7251bf;
+ a4c84cef64f6c9b53bf8f957f4b03cf43e89957f
+ 9a3e8128f8743d16687b7bb8deb9bd205b70e04c091d205c
+ dad9e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf7f1bfc
+ 338ab0ef5746ea8fdcccd213e33f7e8a5718fd25014107c8e7d715a92add9589d1f5c054b2d983514605ec590294a319b9802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70
+ 77b5382bf3a2e0f3545f398ec08d94825572da0ec6bee8d16a98d42f246eaaa8d049499dcbb872e5d751e700b3d2edff7264c1eaf2f0a0c8987932a53e171e62c2364212f3ef3405
+ 87c558d944a7c325965931188213f6a37719581ade0d0561;
+ d17d4569eaff59a332ba58d5d5589bfe079753ee
+ 1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6
+ ""
+ dda7abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4563d405e51881e99027b8ab9aea3ccf860b0009740763d96836c5f87b95460938de128
+ 0f50a0d3b7e41c19a9ed4c679ae42b4ba5055d3e9c60652c07daa390cea5c499787ffd7dbb1cdcfe095ac7549db82c3068e053bb2fe3fd8a5749d653be84a5ffadbc1dcfa6a400006f6badaa62
+ 14270e56d692e540aa7cb92b1b285eaf00c6e183c6f03341;
+ 8c69d80ea12ff4bb5f069b8a2e86041c1b9fc214
+ e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa
+ 6c36800d9645563a308ba60076817523bd2abf1261b089d8f23a9c2835076a23faac2cdd67771cc667a8331f0a170b66283e4f834a06148f302c3973accd56f6f24e33
+ 958b8c2e2352fd61e4fa8fec816ac861a8b33779f09e7a10fc02a8f48afa3080ee119a52a9a817e4f2b94b0820cab383a8cffeea7c486315799dc875fba578c8ec4837898a92142b5b0677da1a
+ d9933fb77ae951691f9b11b7eb9a949191c1a39d09e4bc78a0be75bc8c101ad281eff87a1f5da724d79235e949a589b39125d0a91025a9e126054d980307b934a590687c64e457991a88895367
+ 03e5dddeb49ab69f6a062242f8c1a0d1d2efb55895e03a83;
+ c273117b45bcfff5d5f8b6fde2893232a9f81d14517ffae475f6b94a
+ 43a67b3d380d2f9aaafe2dd721c0095c8808847689211450
+ ""
+ ""
+ ""
+ ccc44a234758478dbf8787d423d646f61b0cda1598fca3bc;
+ ba8095ffab1eaadf66fd22ac1976063e113ab61f813e28a1397a7974
+ a1d7f4220c785fe426a5a0e80f678d404147842941feeffd
+ c2
+ ""
+ ""
+ 49e97ec66094c4bc5ab035aeaf6cc43dacae0f582021e584;
+ eb44dc8c0d5e8f444f7f4e0c893959b74dc23a7bb40e7e0013e51506
+ 86d2301b43a15a84e81d7f5cedaa49e2414ebf47970e5604
+ ""
+ 75
+ 48
+ 8128cb7db1a943e0cca309d9204164fbd9c34ca6c07f784c;
+ cff206877de69146acc3ab6cf8556b7aa776945948d1b8834df2196c
+ 92ec1718dcdeee0d52d9539726d2810391b3f9d10c39b07a
+ ""
+ e8f08ce7cee4758a386a9943e97dedfbe61e737882cd09c2b9a80f34c0fde11c2481b11fc76bfa4dbf710a9e544e0c536ca1e040f9ad5b04140d98edabe08485290a4d87d13b0739
+ f8e281d776b2fe8726809be7abdd62c22c4b523b7613a5858be2a07021ed3dee1945f62bb37cc0be1de3b1e475ed5828ba13a26f34e2651da980ca02602c5e58c8834ba9e8cb5e5d
+ 97fb24449e5402189c30187aedf9627577f0397158331735;
+ 8a1458c2c6b61dbdbc1cccada8c1a0a9aabb6c4e3c3554f8fb1ef616
+ 14c270295dfc0ca6551ca4bdb75359f91cb9d921056b7de7
+ 4fc9a9b37154ce6c0b396179d31f06a1dd5982cbc0d7cb23841da1ae8f4ae480cda98ad6cf2bacf6f9fd3f821330c43f3df6c2b3fac7cbcf96523d4723f91801325eb8553236651c
+ 96788d73d192ee53b3f3ebd66ddd98cedbe88e245de25b1593b70f8601562d90a9b59ed034a867642d25d54756fa5c47f16f64b837bb4926214211a1c696ba172010abb433922a22
+ bcfa139e6fdf6e5bcf96a5c29f8e0145c1d613edd25b9653bf6772d21bc6ae69fa71eae2029716605cf398247b7f2e5a97c5886d94fd674c40b5d42218c2adc7f84770e7288fab36
+ c92aa7646695a597df47a2c686ba2abe2b0d20caa4052185;
+ d9fd881519165eb9d85197a21cc34ac0d5ae7be8dbf98e4ffed2cf6b
+ 1372a5aa47b54fd9d70c70e117bf1cae71b3a56f0e7d839e
+ ""
+ a59cc783443d64f2ed6a29b96856beca34fd6544bcf86b799e2a1681160ccf055f0fd3001da597a1406d465b7b1419ea51cf858f938f6daafbd656445a09898eaa96ffc3d1d2e31e4e34c94b8b
+ 2cc3069cc00db4c51fb54ccb6ed44217a5169eeba4d3fae16878af2b0f969d5ed42da3fe8901645369768e0ca33cdec8cd422a0442c798d8a214fdbec4564b09d70666884ced9a0e64bc9eb3d5
+ d9a32a67db1fefa016cd7961df3e0a9e9949168242a2181a;
+ fae64825ecd75a66d88eedb969ffe07669845ebb7a24c69f13d099f4
+ 7166edf54538e88fbf433a7ff212085179e79771f6eee728
+ 3ab178ef2b800d7b969da05780ffc1ba78c70dda7a4ca2a25e771702fb1901ecfc8a959cb8e75079bb018ccc8c54f31b450e88f8e9002926ad0284c738f4cb0f58a1e3
+ 4c8b15ad930c1b627235a2cb84241986c251f5b70be2367f047265264e0da72efe8995e6c932a17eab511eddb8e4ba463c663035a6ae8a7a899e4279d54d03f0e0f3e961dcfd40088d5be74088
+ c077af8264ca4bd0902dfe7c6f43dc4232c619bae8d151f9be98caf39527e373efec0dc9fa55b62f207b533724b78935255a608e9ac32da258e8f4549d473b95b9057900b2f715425d19804801
+ 125a60f3f7f0913f203632d93f4f2cc70e76ca59cfda9a57;
+ e4097efb0368c7e2f431ee69
+ 88cf2a0e9ebeb3de79c4f86c9e4fba61339d6d907eab7707
+ ""
+ ""
+ ""
+ d040e427a7ea51019b49c65a9c38a803bdffe3635357b8e3;
+ ca48ff5ba1ae93d16225d469
+ de5747bc1addf5748729720a320fe14fd29cfc59314fe207
+ 9c
+ ""
+ ""
+ 2bd8090e45ccb18c92e3c133a19e0a3d3bca6dcdc4f5d591;
+ 0a2535ded56112d6e3d33dcf
+ 7c71cd7d130323794e3da84a9df69703a9caf02d2a8f57ac
+ ""
+ 71
+ fb
+ bdb4cda8932cacfa59b5e1635a394ffae6a03ba034759e86;
+ e554a6850d55882f8c7ae699
+ 4fc8528bd18c374fc43581d2f72a89584a2404a059f7f99c
+ ""
+ 7241a0c879d6d4455b382a9ce757b3e7a1d07585ad9d7ea9c7c9cf54f3bc6d94238ab56d738e02abd651477cd726d6f3ebcd6fadeab50906642a7de6496247060e7be3632ed9bd94
+ b29f37bc84835d3cead667fda5bcaef6a0b93a0e1e79169f94d0111d28e0374fe7cc4a2f9ac274c3f31121d2a1058094b6ac1707f92c87a45301cc2451eebd8501d63a8f561d2f86
+ 40f807380b82f25a620597ef741e74638ccb5a7a58e4bad4;
+ bb42f45a8733b2cd2df9d1d9
+ 05cfdb29983050d6bcdb686a0c897031ad09a5b8fa687ec3
+ bad8e18dc2ad361f1e226e78876cd35f86c639733c5cd84aed8aaebabb7e0f24edfd9710b7bca91b612ea37fc5cc09f7f62f66b423fcd2dec5de24d264f2c839839c1b06319f687d
+ bc68d9f07fd41ccb4f8cde8de201ec2680332bbded4883deea0b58b54bdd13c17ef292b0ded3caeb5e57fd21df10bc6186265ee6ea45907de6cb822fb2ef953aea358a03e0fce2e1
+ d3445b37b2ee6f261baf94fd09ba0121b1ef9a8dacddacff5ed3bf46c36cfd1f2a5e9a1e35b73299bd31137a2a7746c8b46eeda7fec1662842934d0d1b41d240a40886e17f3733d1
+ 2f65d5e606ea39bd566246b137733278aa2942ace8edc2fb;
+ b9511bd332c86e67f123377a
+ 8f0256b8dcc73ae1b3c6cd3f104e3cb24284cfed17811d64
+ ""
+ d492d39ea7496993a25b072945d83f923e66b0a6689cf0969c003a8fca80e322a4b1bf050c1220450433efb6b6d8a2d820cf27a64b9d47f636845dac557bb3e75f3a18fb8e173416867fcd0ee7
+ 65bb74fac682e5422c376f255b91a383334486c836f5f5d578b276ef240206a1761e2dc66109d2b11c4b2d25411c5e0a86316501a1a22a779ed2be816b7b84ebbf1c0cbb41a332dcc43a8d0912
+ 0023df18856b33924dbab9d86440a7fd289d314aa17a282c;
+ 8ddd9236beec76d55ed58b10
+ f91d07a037791ab96e83c4bf2fb5b205e592c172a5cbc194
+ 56c95c1bea6079f3867e52d663cb3884b2a0a8ff825df752423f3179bfeb89eca385f20ddce5f1f23564672e370ffc37d400a31e8aac1d426ce10df73c5ee478b3b63d
+ 91024780e974a8a2a0e7a36f84ab1286b627e7d01b38a84a6de738721ed80fd0d7f69fa658abb5a440d304128719b541a9451cead18e4c61d93d1f8fcc53574427767396322b3bf7d02cec0509
+ b58b1c9dc465be8b7159c9f7c4b8ce39c251d39792eda3da5be8ef7b887114bc1b5af143be79983b37a11a0d96082c924d0308999a39734d0d6eee63e651be9a2cb1cb2fc8aa6db22bb146ee53
+ 210b175366af46c07715847dfd494cbad171f2d8ea711f9c;
+}
+
+rijndael192-pmac1 {
+ 60d7bcda163547d348b7551195e77022
+ ""
+ a2de3f1a78f51e79b270024ef181a3c7866c4901882d8f2b;
+ 907dd1dff7dac5c9941d26d0c6eb14ad
+ 56
+ a69a6414d3476b1fe006cd01597794cdd6f335aa776941db;
+ 8f86edd1dc9268eeee533285a6ed810c
+ 9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba
+ 8cadcc0f2b6f103713f1875836da1fec0d2492e592969018;
+ 234085406a6136512061f7080cc07df0
+ 591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49
+ 5fb116908156463f1b1f698e9cecf1e6ba99c5292359e8ce;
+ ae1d50c38201a894476b3f102b752eb952953396
+ ""
+ 9590db354fa1be8edc4f4464d0e292ddc6c38614cd7a8d9f;
+ 6f27043eb621b7f65b000961040ef2f9b2fc5fa4
+ 50
+ d4354854bd0f842a2d7d2d1ba28362a1ceea024ee706eb41;
+ 727a9b542cde52ebfda19d0ccc520f215eb57bb3
+ a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f
+ 979f0fbf31f2afcafed5d59414bbbc8629c5c1451ca52f3b;
+ 8f28523c03d4de1600157846b710ee72807a2219
+ bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f7682
+ 9b980aca9bdbb8333cacfd8a76c8bd57e1862136831e194a;
+ 81e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a
+ ""
+ 2e46bc43892089f8eba2108812c2cc5c4ec74ae390223bac;
+ 42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c
+ 03
+ e7cf293a42d599e87773781f8abd4a303f2967de3a36b17b;
+ 7ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9
+ aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f083455b
+ c190a80eb16dea538d732bad5c1d06decbc09ee1a4eee891;
+ 663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef3
+ 15d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e4
+ 54fde6333577613aebc01d5de58556aec8dc6911983a136f;
+ 7479a684b5aefa69a4cd5214
+ ""
+ 1d0a9120f17311d23b4babcdb18d1225ec90fa3276f35054;
+ 7ed12ca986981a874498ad0a
+ be
+ 34750cd4fc57273de4b5858c39bf05da2b0156496adec2b3;
+ f8bc4fcb70e27e98ef1f0446
+ b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc3990844
+ 22e6ac9f6fa50e49f0e24e710d62c83fdb6ade50f102bc31;
+ 5608fe95e81c2533e31c9c1a
+ 9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e
+ d3653df2ff5ca70439d6f154551ba9ff27c5ead8db7af2a9;
+}
+
+rijndael192-ocb3 {
+ 60d7bcda163547d348b7551195e77022
+ 907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc
+ ""
+ ""
+ ""
+ b5d14574dad19385409d38eddbeb6afe08cbc6e40260f7c4;
+ 9268eeee533285a6ed810c9b689daaa9
+ 060d2d4b6003062365b0a54364c76c160f11896c4794
+ 84
+ ""
+ ""
+ ff39389f60d0cb58841212408f59c1313e57029630808bbb;
+ 6ecfa14a7130c9f137120634c9519848
+ a877ff77bf79192a5b50ade5d9cd739a3d1f337f2954
+ ""
+ 9e
+ bc
+ af0809f4d9e7b23e1b98f8b65fd7326aa8b546065218757e;
+ 6b0d27a4ba234085406a6136512061f7
+ 080cc07df0591d8fa21f2dd88374d8cde8e160
+ ""
+ ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533
+ 0fd527536eda95bc7b5e1e67c5737626da7251fb0bb540e3a684656d29c7ee45e19d670d8c7a8a896633608aedb539b5e42d5d9d8d05320777dac9687207f733f137f64a36940ffc
+ e8df4fd3fac5b4b10a2242cc5ddf436f8acac68e0700dffb;
+ 966f27043eb621b7f65b000961040ef2
+ f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f
+ 215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26afa3349829b9458630
+ 6fed54154f8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b
+ 715f3c2b119bc11bd4723df66915752c925e89e5652090168877845f6a5cf40c032b3a54887cf0cbae47edd7623c876a2e3c2035d0dacd42a8820bbd7a20d4991b3c8a98ad7d8331
+ 1b8c5703782c163b28509cb1cb67e2e0bdaf949867dc63d4;
+ 0467cb9fc2712a199e533fa9156308cd
+ ec3f768281e040a9b9a222bd689aef66f5306ceb0c6b
+ ""
+ 08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063
+ fe808b32e6844a1ae334b145183e092c6c18eec5268104868889f5e9f197a831ebea245adb9ead21c16461918a5b48f33720884758d98a55380fb9c088c60a120402a336a646f2499d44e59e44
+ 455d8abc815b66b77c0c7b048215508a1420d501c6caffb3;
+ c46f88de9fd41e72d7b97e23e6eabdff
+ 3bcd211499268878dbf30f1dad89d4b9b12012e4713d
+ f46795630e7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584
+ b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a874498ad0abe
+ 1c8d47ef199e6fb28c25a07ae8051b0785c73579e224b9e85990c66628a3e2a1f21e26735a47c3df4563c23c0e2814fa708566948113cca1fddecf2109c56dacd260689b45c72cedc522b593c8
+ 652c3473b278ac660297c275b0a7beb9501c0d8654310b3f;
+ f8bc4fcb70e27e98ef1f0446b42fb144d44b6d00
+ f06dc188d472a784e0c6f21195a3b9f4ae985511265f
+ ""
+ ""
+ ""
+ b0b54530145be3e9ba77f97799d7a386747f260b20c71d4c;
+ ebd11c164720eef9eb1c8dd0b00951f284649016
+ ed00456331854bc78bf43966eb0cfa9138ddc3990844
+ 56
+ ""
+ ""
+ a7544f3687f32006a57591900a0a73224133ccea2e6c705d;
+ 08fe95e81c2533e31c9c1a9851bc2810d858cbbc
+ 8424d126b807e6daa089c3f9099c5ffb824173d7634c
+ ""
+ 04
+ 7e
+ 13f61abd0de5586dc8a054920b885d81a075db59807b3de0;
+ 226f30cbb7f0e4a973a8cd190107314717a77456
+ f3ff669c732b58db8f48af65f7cc9e3fb90e17
+ ""
+ 21b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff6778554ac
+ f67230d596aba65ecb5d1708bf3eea0c2b8adf346fdb033f4c6dbc9e1b1a394353d4d054ceecf6cc9fd93487da8a5c70feadd5067c9b20dd5096418c2b1d96de1c24ffd51d6c376f
+ 4e72953575d116de1f5283af168f6c9e93abd250d36e966c;
+ f1270485b203a3c1c4c967c0a458cb948bdd409b
+ 687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957
+ f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2ec
+ ccb44d65bad397abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a5718fd25014107c8e7d715a92add9589d1f5c054b2d98351
+ ee2b2fc312e954332969db113f066c2ca26a2a521308ed891cae549afdc3198d1c1e154c73a675cc74e893c95a0e52473ffc15b5540339b3b3a5e62bd36be0e08c5d313d2a1e8cf1
+ a7001eb1a36d838c1425c07ba29c9f8914094e5cad71bbf4;
+ 4605ec590294a319b9802068a9f891bc5ba5afab
+ f8c3122d12d7ff3c41122d70d17d4569eaff59a332ba
+ ""
+ 58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb456
+ 1411b2dc14e6fa752fa2092a36657ebf4e742ad3f74267c6804dd6e9b508c526639d7ade46a49af597966bd5c4cb83ca831f638214498d700b7b52512e7d1fdb1e2e4443d5f2e110901730461c
+ eee75d53b2357e78a5b5aaea134f60f48bcc4a6d0f5c8998;
+ 3d405e51881e99027b8ab9aea3ccf860b0009740
+ 763d96836c5f87b95460938de1288c69d80ea12ff4bb
+ 5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c36800d9645563a308ba60076817523bd2abf1261b089d8f23a9c2835076a
+ 23faac2cdd67771cc667a8331f0a170b66283e4f834a06148f302c3973accd56f6f24e33958b8c2e2352fd61e4fa8fec816ac861a8b33779f09e7a10fc02a8f48afa3080ee119a52a9a817e4f2
+ c4a9eeb3f04799ce6944e8104509fa1aef8f17b5815ba391c356d895d7cf996513eed08a74f58e01e534f0f5c3079c770e255a9278fbe8a3da967a01d5536b1a87292db733862f4f98304a7307
+ 0dbf831632cb781a3ec5c78d99e363ff3e7dfa646fd9e90c;
+ b94b0820cab383a8cffeea7c486315799dc875fba578c8ec4837898a
+ 92142b5b0677da1ac273117b45bcfff5d5f8b6fde289
+ ""
+ ""
+ ""
+ ed4dee5d2f4f878178ede9ff462515501765dd09987f4957;
+ 3232a9f81d14517ffae475f6b94a43a67b3d380d2f9aaafe2dd721c0
+ 095c8808847689211450ba8095ffab1eaadf66fd22ac
+ 19
+ ""
+ ""
+ 2157ffb54f20ad64b0ae17d72c99dcc7f14093b49121bb30;
+ 76063e113ab61f813e28a1397a7974a1d7f4220c785fe426a5a0e80f
+ 678d404147842941feeffdc2eb44dc8c0d5e8f444f7f
+ ""
+ 4e
+ b8
+ 0f3e95269af57fd63b09cac38f5c5f0934a752201dff056b;
+ 0c893959b74dc23a7bb40e7e0013e5150686d2301b43a15a84e81d7f
+ 5cedaa49e2414ebf47970e560475cff206877d
+ ""
+ e69146acc3ab6cf8556b7aa776945948d1b8834df2196c92ec1718dcdeee0d52d9539726d2810391b3f9d10c39b07ae8f08ce7cee4758a386a9943e97dedfbe61e737882cd09c2b9
+ 60b0cded984a7111026de06190745d65af6942a64b7561ae21f68d213ad0ad22ac6fe56c8b7dd756cd9bf6ba13c2c011cd99387ebae0422a4e12e11ceafb0292de2097a876e5c416
+ b28761e6f95f1faef3e4203ed6bc359c0406982b19d8a6d0;
+ a80f34c0fde11c2481b11fc76bfa4dbf710a9e544e0c536ca1e040f9
+ ad5b04140d98edabe08485290a4d87d13b07398a14
+ 58c2c6b61dbdbc1cccada8c1a0a9aabb6c4e3c3554f8fb1ef61614c270295dfc0ca6551ca4bdb75359f91cb9d921056b7de74fc9a9b37154ce6c0b396179d31f06a1dd5982cbc0d7
+ cb23841da1ae8f4ae480cda98ad6cf2bacf6f9fd3f821330c43f3df6c2b3fac7cbcf96523d4723f91801325eb8553236651c96788d73d192ee53b3f3ebd66ddd98cedbe88e245de2
+ 76214c8de16aa91bb77876d7975b49cc15da1a63487133994bda609099c60d7f0d2bbb2efd5af7dc3a276a56220004edc7b1da45c6164d91d77772ed91d587b9caadd20e27d078db
+ 38e894b028899b17056bc987b2ba8fbd7cd6d0cc4a50fb38;
+ 5b1593b70f8601562d90a9b59ed034a867642d25d54756fa5c47f16f
+ 64b837bb4926214211a1c696ba172010abb433922a22
+ ""
+ d9fd881519165eb9d85197a21cc34ac0d5ae7be8dbf98e4ffed2cf6b1372a5aa47b54fd9d70c70e117bf1cae71b3a56f0e7d839ea59cc783443d64f2ed6a29b96856beca34fd6544bcf86b799e
+ c84c85f543c7f56134b2b5e0a48c384ee52d231d0706b2524d39cad86d4e02c085d3c95f96e0e4bb5189376b5276d0a7bdf6b554d92c8984168596abebea609707fad78cd0ebfd0968823854f2
+ 04a3929311c62ac5a52e41328632178462d078e4a495a115;
+ 2a1681160ccf055f0fd3001da597a1406d465b7b1419ea51cf858f93
+ 8f6daafbd656445a09898eaa96ffc3d1d2e31e4e34c9
+ 4b8bfae64825ecd75a66d88eedb969ffe07669845ebb7a24c69f13d099f47166edf54538e88fbf433a7ff212085179e79771f6eee7283ab178ef2b800d7b969da05780
+ ffc1ba78c70dda7a4ca2a25e771702fb1901ecfc8a959cb8e75079bb018ccc8c54f31b450e88f8e9002926ad0284c738f4cb0f58a1e34c8b15ad930c1b627235a2cb84241986c251f5b70be236
+ 7f46b1b9de6077c8ec8d7a07c53c4efe4a7fc60cb8de683164df9faf4b4bd540b6076f4f8449f215ebcb17f73ad9d2d92930e0134be8a56fca74f0f945100425438085e7b3994752a100db09d7
+ 8465609210664b702ba7297e945027461069d9dab09c8ada;
+ 7f047265264e0da72efe8995
+ e6c932a17eab511eddb8e4ba463c663035a6ae8a7a89
+ ""
+ ""
+ ""
+ 867ef0e4e4136a82e85c2ac3a7d6caa7a0c4789af22df032;
+ 9e4279d54d03f0e0f3e961dc
+ fd40088d5be74088e4097efb0368c7e2f431ee6988cf
+ 2a
+ ""
+ ""
+ 9d88b7a1abb6dbaa577fb9032334094d426045ac2b848598;
+ 0e9ebeb3de79c4f86c9e4fba
+ 61339d6d907eab7707ca48ff5ba1ae93d16225d469de
+ ""
+ 57
+ eb
+ af67bb55608d1620c17ca5404cd788d4eb6c738d9597fd13;
+ 47bc1addf5748729720a320f
+ e14fd29cfc59314fe2079c0a2535ded56112d6
+ ""
+ e3d33dcf7c71cd7d130323794e3da84a9df69703a9caf02d2a8f57ac71e554a6850d55882f8c7ae6994fc8528bd18c374fc43581d2f72a89584a2404a059f7f99c7241a0c879d6d4
+ d72178266c9c112c4618e31aa17d1b48ccb51963204539bb07ef387a95454f43c4131e65c1fc4cc28ce70666995d4c86b69f4031edd9abe6e71b27270d75e6c786282401e38bcce4
+ a9b01accbdfccd6b65c684d04a9c836de6b7377c93f066b4;
+ 455b382a9ce757b3e7a1d075
+ 85ad9d7ea9c7c9cf54f3bc6d94238ab56d738e02ab
+ d651477cd726d6f3ebcd6fadeab50906642a7de6496247060e7be3632ed9bd94bb42f45a8733b2cd2df9d1d905cfdb29983050d6bcdb686a0c897031ad09a5b8fa687ec3bad8e18d
+ c2ad361f1e226e78876cd35f86c639733c5cd84aed8aaebabb7e0f24edfd9710b7bca91b612ea37fc5cc09f7f62f66b423fcd2dec5de24d264f2c839839c1b06319f687dbc68d9f0
+ 598a1235709ceae2308d4c08c0bb6019a8797608d983e6701893d983b7574662a7790da0d68b07299907272fe218cbd19549cc10b1aee2f70c23b1825f734c222369929d78780ed8
+ f8998bcc33440204eb8abe0ae0a50dfc6d59eac76ea51cf6;
+ 7fd41ccb4f8cde8de201ec26
+ 80332bbded4883deea0b58b54bdd13c17ef292b0ded3
+ ""
+ caeb5e57fd21df10bc6186265ee6ea45907de6cb822fb2ef953aea358a03e0fce2e1b9511bd332c86e67f123377a8f0256b8dcc73ae1b3c6cd3f104e3cb24284cfed17811d64d492d39ea74969
+ d66d4a577c1df9ddc37036d5ba8206a6ae9b59bd7d9f096c4184be067aa8c6f836251fd1187edeca358a375cad0bd2ab89563978941870552c94faf821971f77c1583e51fd5077f32b9b5bfd0f
+ 1f839690aead572ae9fd15ee968983dd34fb8dbd4e5827be;
+ 93a25b072945d83f923e66b0
+ a6689cf0969c003a8fca80e322a4b1bf050c12204504
+ 33efb6b6d8a2d820cf27a64b9d47f636845dac557bb3e75f3a18fb8e173416867fcd0ee78ddd9236beec76d55ed58b10f91d07a037791ab96e83c4bf2fb5b205e592c1
+ 72a5cbc19456c95c1bea6079f3867e52d663cb3884b2a0a8ff825df752423f3179bfeb89eca385f20ddce5f1f23564672e370ffc37d400a31e8aac1d426ce10df73c5ee478b3b63d91024780e9
+ 5ccb483f688309a92fdd49b62e82cd6eba809cc87085e08037d2ec45b51db4dee112b3733a650f1ef167d684e5fa46e62ebd7002433c0022874a5839bc57b13f41ac3d221d0ec3d6f727fd1a8f
+ ab66a6b01196d8dd216791da419b5cf132788abed4254d85;
+}
+
+rijndael192-ocb3-mct {
+ 32 9f02c63dd249efeb7f4d8453ee3c38cfc9930a7ef42faf68;
+ 28 abd57fc930c095eec2d8cc466a26ed96ee9b4ce00bc02b32;
+ 24 ff3b3dd8e0f774136f01351375c53605687c0626f0456253;
+ 20 c05ef316f4452a992aebedc3565760cd61dbc635db5b01b2;
+ 16 3e89734e70fa99dbe1571178aa1edb917330932a2ff6ac64;
+ 12 7506243a5da5b0cfccec7138bdd6139fe41407bbb5b410e1;
+ 8 e6aad44d2d891651052c6b1386bb10b5fb782976df1c1e70;
+ 4 6ddb5a25933d8061b4e5e77ec3cd10680308a5dcad517385;
+ 32 906dddd0884c542b133dff61c61f2162e9d95b10;
+ 28 33d3e253c75e411ceeee00c9a0210f7c712ecd66;
+ 24 859cbce898522f5b8722d39fd102288559711820;
+ 20 1d323ad20a20660b568279370228800d724d4c64;
+ 16 7604277e9535634d8a43f77a051914760fba923f;
+ 12 a144bd8fac2616e541c222cb1d8fa1937901dff8;
+ 8 9e4c1fb5aabf111ecb49545a92dc91449345ec77;
+ 4 b2a77eed505ca3ba5edc1a95cac166b02f7ca515;
+ 32 52b3de9c9a0e7a7f3f65170a59a0a959;
+ 28 925abc1d13cf9aa5c0fbcf73ac78b559;
+ 24 08db50d58b2e97c2931e231775fbabae;
+ 20 1c154b77e569e62ff13603a6397bf88b;
+ 16 a514526ab5a5f5622632bf8dbb009f74;
+ 12 1b483b245d9c11c1ad947a74f7303b27;
+ 8 ec31ba263ee64ec9f0e4ff4d7a2498f3;
+ 4 dcaee7b3276238b3d9c946ea970d823c;
+ 32 f43eb7ac65b4f6cc7ef4c1ef;
+ 28 ffdeff14896db787f8b9a8cc;
+ 24 e3d0eec8426fb7223622eed6;
+ 20 7b9b29ffe3f2de6b85b2f542;
+ 16 4a5928e2406cf876486539d6;
+ 12 e1a51d35431662bd48c8d4be;
+ 8 3fcc5d9987661e00bbe41201;
+ 4 c5a4cebe92b555fe8a3bdad7;
+ 32 dce58465343f136e;
+ 28 6ce50ed44f5d41f1;
+ 24 876ecff3404f371b;
+ 20 605b7adeef15c3f8;
+ 16 a56e57ee9e8f5130;
+ 12 48ebd3b98cbda23c;
+ 8 c34363871760230a;
+ 4 484de0d92485471c;
+}
1188d6578860ceb90a80228c344c3d9e72e775cae5d41b0fd9ff9c60d0898fd0
ec81f1cda5409281c7b4d5f698b6ca5d0ec79598571237a08a60a4a0724b739a;
}
+
+rijndael256-cmac {
+ 60d7bcda163547d348b7551195e77022
+ ""
+ a45b5e26bf4b809a89993f34d7b96a1518383ae7a57b51c1ac78cb29a1432a2a;
+ 907dd1dff7dac5c9941d26d0c6eb14ad
+ 56
+ 768cdb787a4de07dc2c7ff3c1846d2fbcd1bcf867dbe9f25607cca4443ee25b9;
+ 8f86edd1dc9268eeee533285a6ed810c
+ 9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd883
+ 00c1e6af11c6d84eda40876c32f4467f45a0f9cbf862545bf05487fd06713dad;
+ 74d8cde8e160ad10997a21635c6d62c9
+ 269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52
+ 8f1442e79bfd604a4400d183e4509b454411b03d63dfbae7db2b03c998db8724;
+ ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6
+ ""
+ 66129452d7b724416120de9f272b2d531a1cc0faaf945ab3160734ae639483f0;
+ c95a97a48030370c33d090c54215abd6b3ad54ef
+ c9
+ 1576f9e568d9bcb014a679b7024aae490080ba401d8808cd9e2b7fe57f0eab66;
+ a38378c5b93bf4f2aad2605faee2b03fb648e27f
+ ff63102758fe2b69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2
+ e2ebc3f8e727de99c6fd46bef8e7df52599e0f8de53567bdfbfd2b52b907e7ff;
+ 712a199e533fa9156308cdec3f768281e040a9b9
+ a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c4
+ afc6c9c54cbe70a0e7fa6146a5ed4ae9ce68a1d609af79708281be0c2715c8fe;
+ 6f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad
+ ""
+ 39733f351c3e4a5b686ff0a932407c4dc2f41bb387592881b3f92f915ece1cd0;
+ 89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20
+ a8
+ b6caa7f9735ae9ea8083faa068dc284cd5d14332984ced7f46d3e93bddd7fac6;
+ f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f
+ 1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a874498ad0abe
+ 7fcf4a19556a8ba23df01de57087481a425410f3f092e4f801a681625b713935;
+ f8bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784
+ e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c
+ 6377ee34258253260374a4654c8bd727bdef4e5921e59a770a8a6178bc61620f;
+ 5ffb824173d7634c04226f30
+ ""
+ 4ad4651e26e46ac9b3890fc7adae23cbfcf808d96586a4c88a27c6a8533b51c3;
+ cbb7f0e4a973a8cd19010731
+ 47
+ 18566621f2c24c55bd880e8603461de80fcf01ceeda7bb7aedb4253204372e14;
+ 17a77456f3ff669c732b58db
+ 8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967c0a4
+ 16a524c850d351e451cd482587f4f622542283b085e16ba423c8c54085b08350;
+ 58cb948bdd409b687fa3a682
+ 7b480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d
+ 3e8977f205b75e6fae2105cbb8cdb26f3e8057957ce69b9e6be62362bd225924;
+}
+
+rijndael256-ccm {
+ 60d7bcda163547d348b7551195e77022
+ 907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268eeee53
+ ""
+ ""
+ ""
+ 39e9b611;
+ 3285a6ed810c9b689daaa9060d2d4b60
+ 03062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137
+ 12
+ ""
+ ""
+ 2de43d0d;
+ 0634c9519848a877ff77bf79192a5b50
+ ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a61365120
+ ""
+ 61
+ af
+ 8b7456f9;
+ f7080cc07df0591d8fa21f2dd88374d8
+ cde8e160ad10997a21635c6d62c9269029
+ df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f
+ 215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72807a22
+ 87e66fdcee4d517cac9c5df8c9a1250f9b4c4661766cc1f92ac99e539d615f16e9e922ed9a2858ec999c25a625c576360c99583babc0f0a2730dae7a28d505f72933cac1614ff406b2e57a81e42f6d939201ce863d146cea017de5759a440f99
+ c225cb11adf2da0fe435a56b3c32692e9b469cd9a3d596e980fd06753fae46e6;
+ 19bfb474fd71d891f24bb65d1563259f
+ 9eb53b571ea629c54d57dd2d42f70800df
+ 9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c
+ 037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f083455b
+ c16a37dd487a042d5ef9f8e37dd62300e0f990b5d8b4475610726cc6c1f459079618a0e57a0c1a7edac73d37fc0b34772afc4db80db4b0955fcbe20cec2f09396f6b6935df5ba6a663eeda17386b5c2415a5ceba8da9f024d7ed0375d172cb64539a55c133
+ 997e534457f57e31ac0bac767af4763e3289abe713dbe1b044dcd9d06e587077;
+ 663e4ee1315f3c8f2aebfa921451dcd1af5813b7
+ 0d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617
+ ""
+ ""
+ ""
+ c17f8532;
+ 669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16
+ cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970
+ e4
+ ""
+ ""
+ 9238fb01;
+ 7479a684b5aefa69a4cd52147ed12ca986981a87
+ 4498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06d
+ ""
+ c1
+ 55
+ a72c2d2c;
+ 88d472a784e0c6f21195a3b9f4ae985511265feb
+ d11c164720eef9eb1c8dd0b00951f28464
+ 9016ed00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db
+ 8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967c0a4
+ 58aa01bd9e621d51a56834475abe47e312b92c5cbc9ba2bda0b6c93f8205dd034dc7ea07fff025df7357c96de86f1abb81b7acd50c8152c2cc0b858a1a2269ef527b5b29b58b365e85e6a0c86c38f84484dbdb52451e8b9f3045b87d027d4274
+ b0c5980dd1d865f66cf8afcab40eef4768d8eae4e3df3af89474ba26805dc97f;
+ 58cb948bdd409b687fa3a6827b480aa3a4c84cef
+ 64f6c9b53bf8f957f4b03cf43e89957f9a
+ 3e8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397abfaf529ee41cf9a05c7efedef3401539c51d2a90b
+ bf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a5718fd25014107c8e7d715a92add9589d1f5c054b2d983514605ec590294a319b9802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6
+ d60e61dc2da592c48e916f6185dc2f21f8f81967a0606a90d65d2cd698eb7a496483fd545a49496f140faa6f9faa01ba37877b389f62827032b6f212f454415fe8b55511cbe76dd33304342e41def358962982d37f447e45ebdf80e1da9e971926bb261b8f
+ 2d6f1893de28ec8fe81d627c746bef1734bdbf70342adf8366fd9ee123893f8b;
+ 699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68daac90
+ cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d9803
+ ""
+ ""
+ ""
+ d5c932ed;
+ 98bd94e66eb4563d405e51881e99027b8ab9aea3ccf860b000974076
+ 3d96836c5f87b95460938de1288c69d80ea12ff4bb5f069b8a2e86
+ 04
+ ""
+ ""
+ cc3630f9;
+ 1c1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ff
+ aa6c36800d9645563a308ba60076817523bd2abf1261b089d8f23a
+ ""
+ 9c
+ a9
+ 893c9eb6;
+ 2835076a23faac2cdd67771cc667a8331f0a170b66283e4f834a0614
+ 8f302c3973accd56f6f24e33958b8c2e23
+ 52fd61e4fa8fec816ac861a8b33779f09e7a10fc02a8f48afa3080ee119a52a9a817e4f2b94b0820cab383a8cffeea7c486315799dc875fba578c8ec4837898a92142b5b0677da1ac273117b45bcfff5d5f8b6fde2893232a9f81d14517ffae4
+ 75f6b94a43a67b3d380d2f9aaafe2dd721c0095c8808847689211450ba8095ffab1eaadf66fd22ac1976063e113ab61f813e28a1397a7974a1d7f4220c785fe426a5a0e80f678d404147842941feeffdc2eb44dc8c0d5e8f444f7f4e0c893959
+ 696865f6691e1d423ef29c34769d153e154cf60958dca4671f95cd3e798b078ac5bb61ac610a204ae8fa705e0049e67e33524939589b79f2dd0a4afb1af3de3be22f63024fbeb4114fe9d63599cbb6bbeb46b6dfbff4c4c4045a195a9f6e841f
+ 2f8b9f3db32f5ac54b01d587c12a62439f1c211ae0d95749c8c6307a53f94832;
+ b74dc23a7bb40e7e0013e5150686d2301b43a15a84e81d7f5cedaa49
+ e2414ebf47970e560475cff206877de691
+ 46acc3ab6cf8556b7aa776945948d1b8834df2196c92ec1718dcdeee0d52d9539726d2810391b3f9d10c39b07ae8f08ce7cee4758a386a9943e97dedfbe61e737882cd09c2b9a80f34c0fde11c2481b11fc76bfa4dbf710a9e544e
+ 0c536ca1e040f9ad5b04140d98edabe08485290a4d87d13b07398a1458c2c6b61dbdbc1cccada8c1a0a9aabb6c4e3c3554f8fb1ef61614c270295dfc0ca6551ca4bdb75359f91cb9d921056b7de74fc9a9b37154ce6c0b396179d31f06a1dd5982cbc0d7cb
+ a6c5eba6167038a4cad7ba1d4b56486454220bbb137441c9dce2aeaeff28d7483ed42af4e09ada32dd9378f098f84a1490feb1b69fde424336de7ee13cf3d78e98b06d4c256ea7b2c8d09a844183d4fbd9ab8cb1e5daaa68065c654f913cf993f24352ea79
+ d12d64dd43380368b4c96be31ed6506d5062d06db2b9feddd8eeaab6e1e05328;
+ 23841da1ae8f4ae480cda98a
+ d6cf2bacf6f9fd3f821330c43f3df6c2b3fac7cbcf96523d4723f9
+ ""
+ ""
+ ""
+ acf8fba1;
+ 1801325eb8553236651c9678
+ 8d73d192ee53b3f3ebd66ddd98cedbe88e245de25b1593b70f8601
+ 56
+ ""
+ ""
+ 3ed65cbc;
+ 2d90a9b59ed034a867642d25
+ d54756fa5c47f16f64b837bb4926214211a1c696ba172010abb433
+ ""
+ 92
+ e3
+ 1e19bf8c;
+ 2a22d9fd881519165eb9d851
+ 97a21cc34ac0d5ae7be8dbf98e4ffed2cf
+ 6b1372a5aa47b54fd9d70c70e117bf1cae71b3a56f0e7d839ea59cc783443d64f2ed6a29b96856beca34fd6544bcf86b799e2a1681160ccf055f0fd3001da597a1406d465b7b1419ea51cf858f938f6daafbd656445a09898eaa96ffc3d1d2e3
+ 1e4e34c94b8bfae64825ecd75a66d88eedb969ffe07669845ebb7a24c69f13d099f47166edf54538e88fbf433a7ff212085179e79771f6eee7283ab178ef2b800d7b969da05780ffc1ba78c70dda7a4ca2a25e771702fb1901ecfc8a959cb8e7
+ 0a55d15edec4262afac43ca1fe8e3d9ef79463234eaa45795af83c017e36d9238ccb373eb40a3eac59f2759558e25e60769170f0f38a433a24587c8c525db9af75cb4a3e91f0dd7cc0d59599eeb07761a35ccfa9c548b681e2353c743f60a4e4
+ 9995e65234d6516ca613e75bf36b740df93c28e99cf02c5b1b9ac12479373025;
+ 5079bb018ccc8c54f31b450e
+ 88f8e9002926ad0284c738f4cb0f58a1e3
+ 4c8b15ad930c1b627235a2cb84241986c251f5b70be2367f047265264e0da72efe8995e6c932a17eab511eddb8e4ba463c663035a6ae8a7a899e4279d54d03f0e0f3e961dcfd40088d5be74088e4097efb0368c7e2f431ee6988cf
+ 2a0e9ebeb3de79c4f86c9e4fba61339d6d907eab7707ca48ff5ba1ae93d16225d469de5747bc1addf5748729720a320fe14fd29cfc59314fe2079c0a2535ded56112d6e3d33dcf7c71cd7d130323794e3da84a9df69703a9caf02d2a8f57ac71e554a6850d
+ 69a364a10ea53ab96e931e5c449427a40d2d571e8beb2dbb7577edd3c581456358be681655e7490b139a138ba9ffcf95636344a6886ae4e222f46ea7e5e6e4529c75276734895d322770de34b9919b2e7add2bfab0952d053b8991f39198ad4c61391d691e
+ 77bab4bc3ed79b9a7d89be7f7a3f82f34628063596ce73129905c0020b9bc0ad;
+}
+
+rijndael256-eax {
+ 60d7bcda163547d348b7551195e77022
+ ""
+ ""
+ ""
+ ""
+ 56ae717b581681545bef99f97673b07d76c5f29cb1fbb3db8b99d59c99ab042b;
+ 907dd1dff7dac5c9941d26d0c6eb14ad
+ 56
+ ""
+ ""
+ ""
+ 1284871421d525f5fea4eab5cd3236ad719701f0ab7e0f5de835de37e89c8828;
+ 8f86edd1dc9268eeee533285a6ed810c
+ ""
+ 9b
+ ""
+ ""
+ de3475c1039364a38f98e4ec3c432edbe31bed2b4ae2c5bad8d3ba1ec6338ad7;
+ 689daaa9060d2d4b6003062365b0a543
+ ""
+ ""
+ 64
+ 8e
+ 9f58b74b0c8c4612ddd9fc1a0a2ade2f129882dee66e9c7943d55fe32cf0c7cc;
+ c76c160f11896c4794846ecfa14a7130
+ c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f2954
+ 9e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a8
+ 94476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2
+ a59e5bba670ccd7caaa3eeeb6f7e45093846a32546fa3523791b2f132404d9a86f0f35fe46232811cd5b654c9e275c6db7f79e530cde3ace91d7a637ac4cbde01e09560059afc2da7aba6c16c5dd412608263b33187e27bac08512b611bf3819
+ 21088f614b6dc3f1ca5a6cc1dda35b59373dc77f9a4b91954ec75ab8ee1f3d4a;
+ b03fb648e27fff63102758fe2b69ac26
+ afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee7280
+ 7a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b
+ 0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f
+ 7e11239c076c83d990ba728f083f5e6937e80b81d31b1e8bfc4dd1341e4023a3b403fbdfc112b81795038ef923c300ed1c7a49399f873632ab1d48991e4484e3ed7ecbae505e69dea28e8bcb34d19a4c825d17ae6b3000d69c7729c66a4d75232e392573c4
+ 37ccc36ae5a0cfb968bc686d6c61844a13d059ade69efb70bffcc7f4527e7db7;
+ 1dad89d4b9b12012e4713df46795630e7952d22b
+ ""
+ ""
+ ""
+ ""
+ 2a04e16b231801a616818eb325a3b6b4455ad7f0feb221fc9cf7ee7ae1f77975;
+ b02d7100b8b649377d20a8f083455b663e4ee131
+ 5f
+ ""
+ ""
+ ""
+ c60fd57a9134b835c1a6ff8feb240db21bbba1f499562eda9487ba0046bcdadd;
+ 3c8f2aebfa921451dcd1af5813b70d30ce2f1fef
+ ""
+ 6e
+ ""
+ ""
+ 1c74926dd4c104bb6b4547117904d442e2f3a5f26fe303f2777d83043f70f6c6;
+ f315d0798391805da08da3aefc5f8584b7c5e617
+ ""
+ ""
+ 66
+ 4f
+ 4aeae19b9dcd25ad5b8bdfc749075ee42ad0352e7d335e6ef8c1b4d120eae1d2;
+ 9c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb
+ 16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5
+ aefa69a4cd52147ed12ca986981a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0c
+ fa9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374f
+ 484516291ddd8425984d5b20f7951606f6992d02d8c39b044d86ebffbda479500671ec82f8c95889aae76eaf968a38aadba8c8ad820f319a72a6c3ca67d62df2fa069092c12337a22ca4be8438d851ee7ceb4cc6479af0a0cb8b5d6ab3a3c33c
+ 7fcc60c87daa5c131c20ef01161149e738b313743c0165fe272fffa6b8e04be1;
+ fc9bc597f56ccbb2f294b38766fc69f6a9f2c094
+ 5ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d
+ 65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9
+ e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a5718fd25014107c8e7d715a92add95
+ 80366f86356bf3c47346f4ed75e7d21bdc49ccc63b9e606e3b322c53cc173537b7c43254b80bd6c044e2b778eddb8ec32d126c5cdf51c6e3bd13c5f48f8cf1e7596ee01b4ed1d5484ec4373aab252d08f61b8cb40c7ce46b561918f78ae0cdebe8159e900a
+ 8210e8551e214b45eb7e34f359022505753cf6a60dae9a31c4baf9d44abd7f87;
+ 89d1f5c054b2d983514605ec590294a319b9802068a9f891bc5ba5af
+ ""
+ ""
+ ""
+ ""
+ fd2fb424608049e61223ddd23da663c101854f3787a5bf134ebc623070c80e88;
+ abf8c3122d12d7ff3c41122d70d17d4569eaff59a332ba58d5d5589b
+ fe
+ ""
+ ""
+ ""
+ bd15c0ac8e80c6804cb853a059119ba0beec66a6935ffb590c4c6aa53abf9b89;
+ 079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6
+ ""
+ dd
+ ""
+ ""
+ 8828d3a99b3ab60db2a397ddd9f0a0191aebe0e6a0d6f4020f3a281fc67765ec;
+ a7abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44
+ ""
+ ""
+ bb
+ a1
+ 68445bb171a21e07feef9aad62a8069f645b621974ac7260589c4b5a5a309c3c;
+ c8c6254d980398bd94e66eb4563d405e51881e99027b8ab9aea3ccf8
+ 60b0009740763d96836c5f87b95460938de1288c69d80ea12ff4bb5f069b8a2e
+ 86041c1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c36800d9645563a308ba60076817523bd2abf1261b089d8f23a9c2835076a23faac2cdd67771cc667a8331f0a170b66283e4f834a06148f302c3973accd56f6f2
+ 4e33958b8c2e2352fd61e4fa8fec816ac861a8b33779f09e7a10fc02a8f48afa3080ee119a52a9a817e4f2b94b0820cab383a8cffeea7c486315799dc875fba578c8ec4837898a92142b5b0677da1ac273117b45bcfff5d5f8b6fde2893232a9
+ 8f3a1855096bbe241f41b1084e58348e129ae4256d8b73414c3bf9eef729acc2f8a5a6f74ed553bc315b0817f0ab372ac20a58c13dd4e7610f8a090eec8f83189aa3341b36b90254c6893f9b58d3e611b7de06d764f8db43c34ba917809ba2be
+ c8832fe8c57e993797f82b5a17e027e875e72ea488f8baa729ed8d21db907479;
+ f81d14517ffae475f6b94a43a67b3d380d2f9aaafe2dd721c0095c88
+ 08847689211450ba8095ffab1eaadf66fd22ac1976063e113ab61f813e28a1
+ 397a7974a1d7f4220c785fe426a5a0e80f678d404147842941feeffdc2eb44dc8c0d5e8f444f7f4e0c893959b74dc23a7bb40e7e0013e5150686d2301b43a15a84e81d7f5cedaa49e2414ebf47970e560475cff206877de69146ac
+ c3ab6cf8556b7aa776945948d1b8834df2196c92ec1718dcdeee0d52d9539726d2810391b3f9d10c39b07ae8f08ce7cee4758a386a9943e97dedfbe61e737882cd09c2b9a80f34c0fde11c2481b11fc76bfa4dbf710a9e544e0c536ca1e040f9ad5b04140d
+ 74730c45d4e79313a2d4dc9fcaf3b1f00d7a79a35e3cb48139df5572d7d26384bc4547b53cfe81ae1e756a1fce648140acb0a11a9bff1b4a36e3937cfd01530279be056525885a7e33780f3df2404d44d866e2b968bb703ba65050343cce7ac7f37f17d3ca
+ 92dffe3138ec6f4100ff81315d0e0ed88a060a3542e6501979f34cd57c8d39fc;
+ 98edabe08485290a4d87d13b
+ ""
+ ""
+ ""
+ ""
+ 5d70d40b83d7893de0ee19cc043d24f37030e50f04e4670543a7d4bf20fce7fe;
+ 07398a1458c2c6b61dbdbc1c
+ cc
+ ""
+ ""
+ ""
+ 46eaab4431b6623fda169bb2106f6facf930e13c6484bf477e1d2f81e4134205;
+ ada8c1a0a9aabb6c4e3c3554
+ ""
+ f8
+ ""
+ ""
+ a9f67f2c4c00e287548b6518e7d04080973a60280a52dd2c239c63b2ddf3dc13;
+ fb1ef61614c270295dfc0ca6
+ ""
+ ""
+ 55
+ 3c
+ 9ddcbed5f12c814a6b3cd8c58e52bdc8de3a56e19a764633c48d9d1087b0aae5;
+ 1ca4bdb75359f91cb9d92105
+ 6b7de74fc9a9b37154ce6c0b396179d31f06a1dd5982cbc0d7cb23841da1ae8f
+ 4ae480cda98ad6cf2bacf6f9fd3f821330c43f3df6c2b3fac7cbcf96523d4723f91801325eb8553236651c96788d73d192ee53b3f3ebd66ddd98cedbe88e245de25b1593b70f8601562d90a9b59ed034a867642d25d54756fa5c47f16f64b837
+ bb4926214211a1c696ba172010abb433922a22d9fd881519165eb9d85197a21cc34ac0d5ae7be8dbf98e4ffed2cf6b1372a5aa47b54fd9d70c70e117bf1cae71b3a56f0e7d839ea59cc783443d64f2ed6a29b96856beca34fd6544bcf86b799e
+ 876d50aae158510c3d5ef05417d3a1532ec91e08ca4bb7e4abe971f7c37a8664b39483eb2754b99085dd6f33131571ac6132cb202eb43bf75cc87b0b8848ace90af17f93c4793b4cd454b84ccf6bc2c79cd9c5c4ffa670dab2db3933e0b5a79b
+ d6e3a30fea2cb62326007770a28f211f7bd318ca7b4b1e2cdbbffe8b4e5f4aaf;
+ 2a1681160ccf055f0fd3001d
+ a597a1406d465b7b1419ea51cf858f938f6daafbd656445a09898eaa96ffc3
+ d1d2e31e4e34c94b8bfae64825ecd75a66d88eedb969ffe07669845ebb7a24c69f13d099f47166edf54538e88fbf433a7ff212085179e79771f6eee7283ab178ef2b800d7b969da05780ffc1ba78c70dda7a4ca2a25e771702fb19
+ 01ecfc8a959cb8e75079bb018ccc8c54f31b450e88f8e9002926ad0284c738f4cb0f58a1e34c8b15ad930c1b627235a2cb84241986c251f5b70be2367f047265264e0da72efe8995e6c932a17eab511eddb8e4ba463c663035a6ae8a7a899e4279d54d03f0
+ df7563a9736256abeeb7e528afd5868258e5eaa52b09d86eae63321459d7b39a681aad1b3ff8fb742a54f1a07d511162e9b282e50e24ffb8a3ad99b6a284f644cf82fc460fde1bbd338510f55e14ace30d831b9b7339d8129ce086330fad250c6091037555
+ 22faf1c600ec3c2e7eaab84d8fc7b1a5fb63ef32d7161877da051ebfaed826bb;
+}
+
+rijndael256-gcm {
+ 60d7bcda163547d348b7551195e77022
+ ""
+ ""
+ ""
+ ""
+ 155fe406a3e36d08993ed00fcf78b03f9885b8626ffc1c4005c8f54a41d46bbb;
+ 907dd1dff7dac5c9941d26d0c6eb14ad
+ 56
+ ""
+ ""
+ ""
+ 5315b508de9b123b9d77bb1999fe58c3ec72ae1e8beade22bdfb1375e9e18d1f;
+ 8f86edd1dc9268eeee533285a6ed810c
+ ""
+ 9b
+ ""
+ ""
+ 6e1adb0aee567f8e7b58dc7acacf8e2a46fe0d4607e84afdb57725a4c4c62f8e;
+ 689daaa9060d2d4b6003062365b0a543
+ ""
+ ""
+ 64
+ 6a
+ 414c6496cbca39176224573e7c509b4f8df43e5cf5a02344cf75a5ba418322b4;
+ c76c160f11896c4794846ecfa14a7130
+ c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f2954
+ 9e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a8
+ 94476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2
+ 8a0b21b3faf752a732569ab7ca7edc0abf9ba5e9700cb599ab530b374c93ff7825252d41a0eaf26f6eb98fb43ca7e38ecf59c1b6a008c290550aa1fbac54233f5dc3befcfea5687b7516511137cbbbda3bb51357375fae4eb18f948350d4e9b4
+ c70aefe02e2accd4c5e7567b52e38d2f1cd68d2621cdfe4303bee6ad1285ac57;
+ b03fb648e27fff63102758fe2b69ac26
+ afa3349829b94586306fed54154f8f28523c03d4de1600157846b710
+ ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f7
+ 0800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc815178487
+ 4b27aebc1cab373e6f5f94978fbb9dd4ab846dd4c8e6659351837bc075a78d472dac621172e1c5f4c0c184381cac80f27999fcddfc597dc5f1e96106f4c974d12d3755de2be779cb06402712144fd67538d2278d7c79eaf7e965d62aebae459883e94598ebc722fb5f
+ 91201ac6618b71df23cf770cb2be511fa68ab0bb4666fc5a0f166c46fcd2af60;
+ 3f0eb5b647da6794c18b5337685a96ed
+ 65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd21
+ 1499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e61766
+ 9c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0
+ a0359a3a7cd37068cef9616e836e0dc51340c61800a8ca0c9a4e9aec807ed440cfa72d61d992bb4fd1ca3437804b9d3faae47b32aa37b2a2ea954c2bc6a4dfbe55ac20254bc6e65e257316355e37255c3358c287f9a85a809b1a339f928c7bc17d950fd4c7
+ e1169f11b3af523780b7d6060ff7541119b99e149254be2ab460870fb20e0d8e;
+ c6f21195a3b9f4ae985511265febd11c164720ee
+ ""
+ ""
+ ""
+ ""
+ 88853f7a89a9d6ca3dbc23486aeabf94200f7b0222fc7c571c1124d33ad4bf09;
+ f9eb1c8dd0b00951f284649016ed00456331854b
+ c7
+ ""
+ ""
+ ""
+ 705d0df1dae2209b02474644445391b9e6196b397ef49928be8dce7b1ba104c6;
+ 8bf43966eb0cfa9138ddc39908445608fe95e81c
+ ""
+ 25
+ ""
+ ""
+ b1bfbd95d722b50e894535c7eb30e1dadb37f0c0774adb40dbad72e986b9e36e;
+ 33e31c9c1a9851bc2810d858cbbc8424d126b807
+ ""
+ ""
+ e6
+ 20
+ 2cbef7fa0a697ec89874abb08dd7230ff6fb9e0eca0c5a694cab36328c8c95b4;
+ daa089c3f9099c5ffb824173d7634c04226f30cb
+ b7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3f
+ b90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967c0a458cb948bdd409b68
+ 7fa3a6827b480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65
+ aab8f6ea96180e63aa3855416f27313b857947523e7341af0f8f5bd496ee8911a3dcb2db4514168dffb034762a8085a0785e79c8a67ca675f114e9846959d67fa3a333fe4bd09f7a118d2b2571a4a20d8c97c6e9428715a0fcf86a684d22faf5
+ d3bf734339230e22db1a351306eb33335985be58380bfd61d1fdf52067ab901a;
+ bad397abfaf529ee41cf9a05c7efedef3401539c
+ 51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a5718fd25
+ 014107c8e7d715a92add9589d1f5c054b2d983514605ec590294a319b9802068a9f891
+ bc5ba5afabf8c3122d12d7ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4563d
+ 18fbf012c8917f257b87572611b9618701201d22196532e1fd0375bb15585569238d33c780cfd180db25b82bba0886360b0d8068858473f594f4ec46c069a8b5367266a50cf5b11a2285d4f11eae276d1aa24d0a2ae91d6e9d58b3d342ad1cd576faf1617d0b9ef982
+ c55c8221055fdf8cc4ff383c13866d83810e0c355df37b4785e6bd3a260e961d;
+ 405e51881e99027b8ab9aea3ccf860b000974076
+ 3d96836c5f87b95460938de1288c69d80ea12ff4bb5f069b8a2e86041c1b9f
+ c214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c36800d9645563a308ba60076817523bd2abf1261b089d8f23a9c2835076a23faac2cdd67771cc667a8331f0a170b66283e4f834a06148f302c3973accd56f6f2
+ 4e33958b8c2e2352fd61e4fa8fec816ac861a8b33779f09e7a10fc02a8f48afa3080ee119a52a9a817e4f2b94b0820cab383a8cffeea7c486315799dc875fba578c8ec4837898a92142b5b0677da1ac273117b45bcfff5d5f8b6fde2893232a9f81d14517f
+ 6efc84f2bf195615f673c68a0e16fca98d6d9a156a74fb40b74ac9fa50db8c0a34d5b00793827ee2bcb942bea89ba023867de0d00f5d3066c10a035c5f626a0bd92da3b57312ff0e78fc6efdb08d7421a68ee134b28a684ab52b84f9f629009921d80ea20f
+ 1fb7f4fbc9bfc6b37ab7006cd6c661f5d8151f71f2e510af1edc1cb27a97c19e;
+ fae475f6b94a43a67b3d380d2f9aaafe2dd721c0095c880884768921
+ ""
+ ""
+ ""
+ ""
+ 5cbb3eb9742ae2cce92f5e5c9e6fa1875edb5f6ee2207e3ecc61c06370f81105;
+ 1450ba8095ffab1eaadf66fd22ac1976063e113ab61f813e28a1397a
+ 79
+ ""
+ ""
+ ""
+ c1b0dabf513241d592852453e603c0325644288f76937abf90c8b53cb484f508;
+ 74a1d7f4220c785fe426a5a0e80f678d404147842941feeffdc2eb44
+ ""
+ dc
+ ""
+ ""
+ 9b8c23ac703837dc613935ba7bbb64343e29ed170ebf189cc79b301a6aba61a8;
+ 8c0d5e8f444f7f4e0c893959b74dc23a7bb40e7e0013e5150686d230
+ ""
+ ""
+ 1b
+ ea
+ d744d421289bb50dad6cf39990222ffd62c6cb8d2a1511ff27367827224e6eb0;
+ 43a15a84e81d7f5cedaa49e2414ebf47970e560475cff206877de691
+ 46acc3ab6cf8556b7aa776945948d1b8834df2196c92ec1718dcdeee0d52d953
+ 9726d2810391b3f9d10c39b07ae8f08ce7cee4758a386a9943e97dedfbe61e737882cd09c2b9a80f34c0fde11c2481b11fc76bfa4dbf710a9e544e0c536ca1e040f9ad5b04140d98edabe08485290a4d87d13b07398a1458c2c6b61dbdbc1ccc
+ ada8c1a0a9aabb6c4e3c3554f8fb1ef61614c270295dfc0ca6551ca4bdb75359f91cb9d921056b7de74fc9a9b37154ce6c0b396179d31f06a1dd5982cbc0d7cb23841da1ae8f4ae480cda98ad6cf2bacf6f9fd3f821330c43f3df6c2b3fac7cb
+ c4a2f019ff18e90fa3cea69a2f34f2d1f2d498af1173c860fa6b6f20e91781ecdaca5cd4f674027476d9cfb5b921c2d5686d1bc581b70b63feb8042f4d30deeeaf44528b6cddcbaf9a5d6ee4144fe4be1b526f3ddc573aeefe159ad33b9677e0
+ 52b3da4ccdecf74bcf3d144ab23854db12a64df3ed547b78da9214f373d9d5c8;
+ cf96523d4723f91801325eb8553236651c96788d73d192ee53b3f3eb
+ d66ddd98cedbe88e245de25b1593b70f8601562d90a9b59ed034a867
+ 642d25d54756fa5c47f16f64b837bb4926214211a1c696ba172010abb433922a22d9fd
+ 881519165eb9d85197a21cc34ac0d5ae7be8dbf98e4ffed2cf6b1372a5aa47b54fd9d70c70e117bf1cae71b3a56f0e7d839ea59cc783443d64f2ed6a29b96856beca34fd6544bcf86b799e2a1681160ccf055f0fd3001da597a1406d465b7b1419ea51cf858f938f6d
+ cddb79cdcae1c1ecf2734f18295a6e756c73fe54e8939cc5f0f47a3f543800451b17bba62b7af7796674b9d882b05b9b1d0c39a0dfaef98c54f64996105972a740c5a7bc6bfabc63e7d6a8b0924129b9552d6b0ad95028006889241b670a675e4545f21b6256bcd7f2
+ 36fb5ecbc6a1f55d402f7bdb27f362b41cf037ba5b0c8b5f9a8c5b56da81e4fb;
+ aafbd656445a09898eaa96ffc3d1d2e31e4e34c94b8bfae64825ecd7
+ 5a66d88eedb969ffe07669845ebb7a24c69f13d099f47166edf54538e88fbf
+ 433a7ff212085179e79771f6eee7283ab178ef2b800d7b969da05780ffc1ba78c70dda7a4ca2a25e771702fb1901ecfc8a959cb8e75079bb018ccc8c54f31b450e88f8e9002926ad0284c738f4cb0f58a1e34c8b15ad930c1b6272
+ 35a2cb84241986c251f5b70be2367f047265264e0da72efe8995e6c932a17eab511eddb8e4ba463c663035a6ae8a7a899e4279d54d03f0e0f3e961dcfd40088d5be74088e4097efb0368c7e2f431ee6988cf2a0e9ebeb3de79c4f86c9e4fba61339d6d907e
+ 58452492c095671447a7c66a0e3e53cb2c2f6d5d9258e3a44f7e04cbe229248769719166680ff0dbf7d06ea1162b23c71aab1b4732c913bd542d952be48e1ff46df1d55fbad872957481cb71c5728e201cbec2fdc4a58bda26099d3bc64f1c6418c68289f4
+ d9d12a477bc9a18f1b3a4a9ee2b289ff2ea6fa36758427bf9d08f9a4a92b7008;
+ ab7707ca48ff5ba1ae93d162
+ ""
+ ""
+ ""
+ ""
+ 3858f6b0bba7f351a9ede4c2b5fbd5c827e7e992c079ca19cc6f26b830a9c751;
+ 25d469de5747bc1addf57487
+ 29
+ ""
+ ""
+ ""
+ 9fdad124895e10fd8b53e2064b9f2b9d2b3cda627483e9603549c80253e44688;
+ 720a320fe14fd29cfc59314f
+ ""
+ e2
+ ""
+ ""
+ c34c2d5413bddb6cb1ba41791d7911bcb2edd49b6d71773f1454961f1c62033e;
+ 079c0a2535ded56112d6e3d3
+ ""
+ ""
+ 3d
+ 6c
+ b700b74ae722b913ab72d6b1207776e402d74fa4845d602768cdc6deb15f843c;
+ cf7c71cd7d130323794e3da8
+ 4a9df69703a9caf02d2a8f57ac71e554a6850d55882f8c7ae6994fc8528bd18c
+ 374fc43581d2f72a89584a2404a059f7f99c7241a0c879d6d4455b382a9ce757b3e7a1d07585ad9d7ea9c7c9cf54f3bc6d94238ab56d738e02abd651477cd726d6f3ebcd6fadeab50906642a7de6496247060e7be3632ed9bd94bb42f45a8733
+ b2cd2df9d1d905cfdb29983050d6bcdb686a0c897031ad09a5b8fa687ec3bad8e18dc2ad361f1e226e78876cd35f86c639733c5cd84aed8aaebabb7e0f24edfd9710b7bca91b612ea37fc5cc09f7f62f66b423fcd2dec5de24d264f2c839839c
+ 1e698dd38df7f079f6b406910c4c878e2605fe149c9a4f7d575877ade356ef2507eb11ad763a153ef93464f72fb80ccf6670651a22532662e1e33beee419e8a82c8e5f1e723ed1c0db76e90b94a97985e01ddf0b10719a689286b0cdf217760b
+ 7aa4400ac56abdd5ed32f35f5487361a090461e342f11168b122369d31860f96;
+ 1b06319f687dbc68d9f07fd4
+ 1ccb4f8cde8de201ec2680332bbded4883deea0b58b54bdd13c17ef2
+ 92b0ded3caeb5e57fd21df10bc6186265ee6ea45907de6cb822fb2ef953aea358a03e0
+ fce2e1b9511bd332c86e67f123377a8f0256b8dcc73ae1b3c6cd3f104e3cb24284cfed17811d64d492d39ea7496993a25b072945d83f923e66b0a6689cf0969c003a8fca80e322a4b1bf050c1220450433efb6b6d8a2d820cf27a64b9d47f636845dac557bb3e75f3a
+ 10d009d35f7cf513d0f5045d1520d92a4971e792b83901e518ed440e68ed1f4eaa251584ce7703195b3f2d0b19ff558713922efe13ac3e8f8a5d7f608375326aa7a7499274df4e3c963007805ebd4b66c8c52059844edf60327144ab7febb0acc2dbcc82795aef7dfa
+ 02dfe024b324aa1ad7a4a9f1d1cee9c0ba3711e97510fa26ba8f87f7e195bc4c;
+ 18fb8e173416867fcd0ee78d
+ dd9236beec76d55ed58b10f91d07a037791ab96e83c4bf2fb5b205e592c172
+ a5cbc19456c95c1bea6079f3867e52d663cb3884b2a0a8ff825df752423f3179bfeb89eca385f20ddce5f1f23564672e370ffc37d400a31e8aac1d426ce10df73c5ee478b3b63d91024780e974a8a2a0e7a36f84ab1286b627e7d0
+ 1b38a84a6de738721ed80fd0d7f69fa658abb5a440d304128719b541a9451cead18e4c61d93d1f8fcc53574427767396322b3bf7d02cec05093696cec07591ada462271b1d1519eedde0df37a330fe8c22ebd77705917b7e32ae88f45a34a8ba3037235e19
+ 4c8ecebea3c8b010464c18f765a3e100014f564146cfb6382d1e60f5727f37bcfd18f0227c1cc3817fdac6aa202fb93606338616cd140f999d57c36cbfcfd3eb38fb4c4cf5e34a9f0a16b703d268c428e4b3a2b26b4d3a19b08b5468632020ae7cf98a5b6a
+ 305e9c670143f7d88cefabee533e27ad48988b607be91f0aa2f17649d629b688;
+}
+
+rijndael256-ocb1 {
+ 60d7bcda163547d348b7551195e77022
+ 907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268eeee533285a6ed81
+ ""
+ ""
+ ""
+ ed3e1a85a9f92797e1fecc6ea6840a3e0474ce6a9698a720d3df978f3528e06b;
+ 0c9b689daaa9060d2d4b6003062365b0
+ a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a877ff
+ 77
+ ""
+ ""
+ dfb76cec6a750934ea46b81a7e789faca6d7dfb9da0476a03762f15639df77d3;
+ bf79192a5b50ade5d9cd739a3d1f337f
+ 29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd883
+ ""
+ 74
+ c4
+ d5bf8b3be61be60645f84da4eeaf832f082a8c0d6ffc3cc3dcbe0b59bee9de13;
+ d8cde8e160ad10997a21635c6d62c926
+ 9029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e5
+ ""
+ 05da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad
+ a0403a115ebc9ec954f8e240c84a2c9c41241258c510be90585ac99233ae5283d3761b07c48c4c6ed2d445d16d5db78c50e54f9866ba1d5259a887eed0f2efd3c93d77945b1c03f8cb8e30ac431175dbb47f03d3643708aae7f0a329eb433b58
+ a26972939b8f37a37fbb8444db5fe6689b857b639d7b54246144435926e265a7;
+ 54efc9a38378c5b93bf4f2aad2605fae
+ e2b03fb648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f8f
+ 28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689a
+ ef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e
+ dcdb20cd5e1952a7585ea1a5982f5f52fa76a949f615460c564c1f19106a7d06c5b1b194d64d000a368d353e255edb34e405639298630f6dd09210b7218ddbd701c8d29996da07df9ea188c3a58f8f924cae99a9a04822d148b39e396eae384d
+ 4e7b366cc5683e7f8687281003d4c70f2167371aa3cedb3aea7c7b8a3a4bb8c5;
+ 23e6eabdff3bcd211499268878dbf30f
+ 1dad89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f0
+ ""
+ 83455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a6
+ 158feb4340d051637c994afa715876f75eb2f49e832bf4a3d8e7f2d7268f4050406b13952ec6aa85123767375335c65e2651fb803c3399c5f51278c0381b942c575470ef2f2d7a3a003fc174d62c38d4eabcb7108adf2e2eaaf6c74e13b759f37fead1fdcc
+ aaee630716b5f9a791a7941b640408defde3f1747b50bdecde2bf82723fbe523;
+ 84b5aefa69a4cd52147ed12ca986981a
+ 874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472
+ a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9
+ 099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b
+ 374a36cca45ec0f3ea9cc9bc1fb67b6c07a8ab781d118ce9d56988904518f853d2f7551f61b0d87e5afc19c5e732dc0c7d7aea114bb3d7af88cbcd21cb7d06a22eea30921d1277e4e4577152497ff59ff72e55156262bdde9729721c2dc467afb977e5ee63
+ ccbfaf10e2aeade3c72d7f465c271105ca36369bb2644d6da6706702fc8601bf;
+ 8f0911e32d65cc1770a18cbfe6effd1ff6778554
+ acf1270485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b480aa3a4c8
+ ""
+ ""
+ ""
+ acf282a61dd79a7e99740e531b665b12c199e0f66bc3f11f4a08d8fcee8fb713;
+ 4cef64f6c9b53bf8f957f4b03cf43e89957f9a3e
+ 8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b085
+ 1e
+ ""
+ ""
+ 86c6f639096f603555766a0a95549f99fd21ee543f9fad5b44d644c96114e172;
+ 5ca605ac8451399587011677508a15dde524af3e
+ 2bee0646541a42c2ecccb44d65bad397abfaf529ee41cf9a05c7efedef340153
+ ""
+ 9c
+ 8f
+ 51df0841f87c0475e6a8995ff30422fcebc313107123f17dba67767e0dcff519;
+ 51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213
+ e33f7e8a5718fd25014107c8e7d715a92add9589d1f5c054b2d983514605ec59
+ ""
+ 0294a319b9802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb
+ 0a74784147a1986b028e29a9b9ab25645be3d7cb0774e9e5acfbaba28742a47196bb5297b70ddfbf10ce5f1517abddcb29d0fd5b715601a795af85d5503033a19bd63c2533fd50f3bab3c18fbbd7894242f15adad0f1583a5a63ab9745dc712a
+ 9f1f55ba4cb8865c9b9f839183519a3b3c0bb4ecc294e1ea248be64aa7f48f08;
+ 3542a9cf44bbc8c6254d980398bd94e66eb4563d
+ 405e51881e99027b8ab9aea3ccf860b0009740763d96836c5f87b95460938de1
+ 288c69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c36800d9645563a308ba60076817523bd2abf1261b089d8f23a9c2835076a23faac2cdd67771cc667a8331f0a170b66283e4f
+ 834a06148f302c3973accd56f6f24e33958b8c2e2352fd61e4fa8fec816ac861a8b33779f09e7a10fc02a8f48afa3080ee119a52a9a817e4f2b94b0820cab383a8cffeea7c486315799dc875fba578c8ec4837898a92142b5b0677da1ac27311
+ 882bc55429939372f9123390b69f5ce58d26d439fef94063f8b2e96ee4dd8fabd4e9d886e1a1362ea2f95e6e9691c0ddced94c5ecc54893643ed0e75660d43a19a2dff771b1154c860b40d50d68f514c94ee102a17dd347f81954c6ba2266cfd
+ dff24d1115cd7f5f41e72a4709896297a9cc05dade73cb71ae7b26254faf70da;
+ 7b45bcfff5d5f8b6fde2893232a9f81d14517ffa
+ e475f6b94a43a67b3d380d2f9aaafe2dd721c0095c8808847689211450ba8095
+ ""
+ ffab1eaadf66fd22ac1976063e113ab61f813e28a1397a7974a1d7f4220c785fe426a5a0e80f678d404147842941feeffdc2eb44dc8c0d5e8f444f7f4e0c893959b74dc23a7bb40e7e0013e5150686d2301b43a15a84e81d7f5cedaa49e2414ebf47970e56
+ d96d78f641edc2bf6b208202b51ec76d956f5df89026a9f64d9266a2353dbb708b28e63a6999c6adcc265ff3d348d648196d3583e5af294a9bfb31e310f151d70ba5c9735224d768ec4f9400aafcad9aaecf25fd4cd392e35e7c00fe2fd8787deb07f44d00
+ 94837daba7fa8fd70cb03d138e2f493e3db5c9388cadc8e5a6612075fe49b300;
+ 0475cff206877de69146acc3ab6cf8556b7aa776
+ 945948d1b8834df2196c92ec1718dcdeee0d52d9539726d2810391b3f9d10c39
+ b07ae8f08ce7cee4758a386a9943e97dedfbe61e737882cd09c2b9a80f34c0fde11c2481b11fc76bfa4dbf710a9e544e0c536ca1e040f9ad5b04140d98edabe08485290a4d87d13b07398a1458c2c6b61dbdbc1cccada8c1a0a9aa
+ bb6c4e3c3554f8fb1ef61614c270295dfc0ca6551ca4bdb75359f91cb9d921056b7de74fc9a9b37154ce6c0b396179d31f06a1dd5982cbc0d7cb23841da1ae8f4ae480cda98ad6cf2bacf6f9fd3f821330c43f3df6c2b3fac7cbcf96523d4723f91801325e
+ af41f07118ec731dca9ce6df290baa0e5000c68a380a9572679c32437509525919c9b04362bece8721d10aaf0fa8dd9a5fa9f3770c5d5ec1a0deae996255b61fb81f894a521f939cca36fbd9f730ab0d0c17d0689f8c1ee78d4707a36c219a0a60c3fa2def
+ db0e21f651cb6892563f22ec7d4e04c8ab46c22221819f3060f64c5736ee06a6;
+ b8553236651c96788d73d192ee53b3f3ebd66ddd98cedbe88e245de2
+ 5b1593b70f8601562d90a9b59ed034a867642d25d54756fa5c47f16f64b837bb
+ ""
+ ""
+ ""
+ 9f736b72141985c5a64c5888c112a3c872497e54cb822ec3790fc73055d5ee58;
+ 4926214211a1c696ba172010abb433922a22d9fd881519165eb9d851
+ 97a21cc34ac0d5ae7be8dbf98e4ffed2cf6b1372a5aa47b54fd9d70c70e117bf
+ 1c
+ ""
+ ""
+ e7b0f52d7adf83fe817103f61ac846a02e957786c5e605057e41fe4dfa552948;
+ ae71b3a56f0e7d839ea59cc783443d64f2ed6a29b96856beca34fd65
+ 44bcf86b799e2a1681160ccf055f0fd3001da597a1406d465b7b1419ea51cf85
+ ""
+ 8f
+ 2c
+ c93c329ab8f440bb37247f60a5370b34d34ad7decec8e6b2d160acd4c1d12410;
+ 938f6daafbd656445a09898eaa96ffc3d1d2e31e4e34c94b8bfae648
+ 25ecd75a66d88eedb969ffe07669845ebb7a24c69f13d099f47166edf54538e8
+ ""
+ 8fbf433a7ff212085179e79771f6eee7283ab178ef2b800d7b969da05780ffc1ba78c70dda7a4ca2a25e771702fb1901ecfc8a959cb8e75079bb018ccc8c54f31b450e88f8e9002926ad0284c738f4cb0f58a1e34c8b15ad930c1b627235a2cb
+ a213a44a04d450838aa1eff21b53902349c2af2ef7e104af43fcc781b42c9ba22cf484ff71dec347a3f15c73eb2e644fd119297807f96eb604e32bfc76a2dfc2ad53c2ea3842a06e625954689df48ee180d465a55d5df9f2caf89ff7583e6a6e
+ d09e13109159cbee4f1a32379ea1daf61be14ef11778514d79a403df22b3873b;
+ 84241986c251f5b70be2367f047265264e0da72efe8995e6c932a17e
+ ab511eddb8e4ba463c663035a6ae8a7a899e4279d54d03f0e0f3e961dcfd4008
+ 8d5be74088e4097efb0368c7e2f431ee6988cf2a0e9ebeb3de79c4f86c9e4fba61339d6d907eab7707ca48ff5ba1ae93d16225d469de5747bc1addf5748729720a320fe14fd29cfc59314fe2079c0a2535ded56112d6e3d33dcf7c71cd7d1303
+ 23794e3da84a9df69703a9caf02d2a8f57ac71e554a6850d55882f8c7ae6994fc8528bd18c374fc43581d2f72a89584a2404a059f7f99c7241a0c879d6d4455b382a9ce757b3e7a1d07585ad9d7ea9c7c9cf54f3bc6d94238ab56d738e02abd6
+ fcc7943e60d8714fb6070f0bf3db4215b5bad60d25f36aec66ad4ab1c8512b26e5075077d4685495da25e954e00972df8f01ee3e9a6a29ee9d27f45bef2a2d975fa0e2736b59f7273df0489bc440883bdfdf55cceb03bbaac41c4b92bfe099c7
+ 72230dfc699fa95374349b8ab1e55f95234d8f8ffb80eb193157746d5e28f670;
+ 51477cd726d6f3ebcd6fadeab50906642a7de6496247060e7be3632e
+ d9bd94bb42f45a8733b2cd2df9d1d905cfdb29983050d6bcdb686a0c897031ad
+ ""
+ 09a5b8fa687ec3bad8e18dc2ad361f1e226e78876cd35f86c639733c5cd84aed8aaebabb7e0f24edfd9710b7bca91b612ea37fc5cc09f7f62f66b423fcd2dec5de24d264f2c839839c1b06319f687dbc68d9f07fd41ccb4f8cde8de201ec2680332bbded48
+ 1c4d9a95f9cf85283b59197b0449fa65429a7de12cfb25453f01b0f7afcc5534fd6faa80ecbfc8607fe7980370d3042421385d7c684ccf71d4170db54359fcb4cff4d2d6126b587fd6b2b50279ca190f605c740546b2a0a75055c0cb2cae2506a5fd23be2c
+ fccd1e6489cf18fed4f745338cb06d0a61a6c692d72bbab24b3fa0ee9e9e2a88;
+ 83deea0b58b54bdd13c17ef292b0ded3caeb5e57fd21df10bc618626
+ 5ee6ea45907de6cb822fb2ef953aea358a03e0fce2e1b9511bd332c86e67f123
+ 377a8f0256b8dcc73ae1b3c6cd3f104e3cb24284cfed17811d64d492d39ea7496993a25b072945d83f923e66b0a6689cf0969c003a8fca80e322a4b1bf050c1220450433efb6b6d8a2d820cf27a64b9d47f636845dac557bb3e75f
+ 3a18fb8e173416867fcd0ee78ddd9236beec76d55ed58b10f91d07a037791ab96e83c4bf2fb5b205e592c172a5cbc19456c95c1bea6079f3867e52d663cb3884b2a0a8ff825df752423f3179bfeb89eca385f20ddce5f1f23564672e370ffc37d400a31e8a
+ 277fd76c5b58942c48687f4153c8d8aa6521902cff09bab07145801225bb2823fe4e112fcd11726bc62da7864baa800905c9392017a574d966aca87da54d481e320934c4d5b8858bb53c9f91170e96edf3e3b6a583677e2eb0f6e876162ebc2d9f9d5f59d9
+ af850a26c1eaa2af0c507d84542fd2a5dfda7ad3f6bbd94d7202716f0bd83b66;
+ ac1d426ce10df73c5ee478b3
+ b63d91024780e974a8a2a0e7a36f84ab1286b627e7d01b38a84a6de738721ed8
+ ""
+ ""
+ ""
+ 1a65a7de04f027cc7ee41a321985a03044b009409ea0a04a6ef4f268a40d647c;
+ 0fd0d7f69fa658abb5a440d3
+ 04128719b541a9451cead18e4c61d93d1f8fcc53574427767396322b3bf7d02c
+ ec
+ ""
+ ""
+ 2257228003251d6931be43f6f65654859ae865666736fc80b7ce6feb69cf8c4d;
+ 05093696cec07591ada46227
+ 1b1d1519eedde0df37a330fe8c22ebd77705917b7e32ae88f45a34a8ba303723
+ ""
+ 5e
+ 44
+ d4ef8d10bc4dfc028117bf6b79fadd4498eee972464c390c38cdd44837eb3a8c;
+ 19a394be4d26ce47317d8087
+ 684456b4cfc5555e925e3e7b2ebc829b2d0505ea617b0ca9531bcdb96040d390
+ ""
+ 40e632d562643ccb64286303040fcaf679e914eaddc05af8843ce6a427b99a5dc266de31c09165237eeefe4b58cc034b9f099f04678c2a9da898b39324cd3087a651014f6796f9c4881d89e127e62221e47e57badd678d490c2f320ff8fb1c42
+ 2702a4cc524f8c7eaad3198222eb31272dcbd5885798ecd2767a8e9292550feef8f1a6ce4c615967cc154def805d429a2964b5202955972c106deee2444df7dc0a3ba8940bff435cde364f1a43e4e5081d6bc4296ffcc3f907152b1e01e892ea
+ 37ede9a353c66446268a96e3101e6716b5a0875413bf2cc714720277885cf14d;
+ 761bd439f3e96dc0ed1d5b21
+ 69912af1a4e2c533c52ba3e8c71c23a089e231480aa63c484fb34bd522397f10
+ 2cb8ecf4f64e329884fe73be257a753b38200bc23f94a079bde2dd98d813655dafa15b85419d15c41a5153cce5d0e8c8702db2ba11927589678d4f7b8fcfad4818c411f15f452300903874f9a532ee46496ae753a2340af7b91f9632fc5ae71a
+ e18b40de751ab6b6761ca16434a9935e466e11c1cb072f32a59c313dba3db646ae909a096697d9a7b0556463ff1126ebc43263391424d02739d0787e804d8f1dccf6c897a8a48431324324041b5302ccd501b538bd03d5cb5c90d1fd3f7d2be1
+ f03d990fa20cea58d5d15c20a6a8479f8a2650c245da7d5e8505e2e32c924d6332b7e8cb40139bb17a2b6b95a200c1f4cbf967ec5ca8bbd04db6f70a767067d46fcbc066aeac04f2a3f9e647b290d31f3de21a9dd0e757274c1623319d1f98bb
+ 129dc99b2b2d0335f5453ba882fa4469e4617169fa9f3394fbfeb4a9fb68925a;
+ 87a787032c79ed900764ee4c
+ e1d3fc042c084f7d8c0c48ad7d6f1eabd0fd1ec24a88f26734d5c8d92dbd873a
+ ""
+ 8fe113090d401bea4d28ff49f10ff593adc258e091abd31b62dd1735158f98765970acc6602da063aae01a2a199d3a4f37a5f062d216d2053a83b5d3a0488ab0d2df631b2892cdfcf9fdd0f37de9ed67179aeae82fe00009428b297b553230a6d917fa0c1a
+ 7e3a6085662512c823d6d9929dbcca2e1833f6589a38fba924c2e16d6a1d050b7442fbbc2dfd750c76235c96aef4d0d9388c457c5c368c58325aa09623297e6c4a5f19b668ec3ace50bad6c64824ccbb0ba3c72fdc5041ec93d3f231321f687906e3ebd93b
+ 54e6538ecb2b4903cb6f375cb5956c92de38b1584b08cff45916a3c4b1f5ac84;
+ 233c9ebc8a4cba45b20543c5
+ 40fc1b9dbce078b87a1534acf03897b95a3f372e9f6c5a5f2ae44a7dbce9ba43
+ a39089de20de70d0544b5151db0a16e9769e8f2fc12c7f839fab269a0056284a697ffd4113a1cf43b5d5bdce2d86dead83f5a356e9106bedf908db61f1119f9700260ea9379cc7232184d217158fee8ca42e75614739e9007f234f
+ bcd86b0ad8f641a0449b6d9b0f99d1cb4a57a4d6f987feb0ade90aa1d81c4f497b3734be301da3e25fe692629db57311f422f3a1573f9e0553a23e96265e4326fa532d7136863e5b4bc6c99ade3d4eb23cacdf6e42ad8ca13187eba1532920ba31582b3793
+ c65596e9c53e56de712143c2be771a3707bce914410b2e32fe484f74a6210d6ccc48122d4df80f2fdf5b3da056b8742ef07b5ed7c038d18d61da0f5e6584c6af306d1e11ed69ced0594202b10cde788cfe963d38846daa71158909e5fc051dcd0b11b2a8c3
+ e450cf5a72fbfbc72c1249de355a6c3fd6efbb4bf28f68c48b286266a7a2ec6e;
+}
+
+rijndael256-pmac1 {
+ 60d7bcda163547d348b7551195e77022
+ ""
+ 932f0d9371e20b910a772eabeed12feef4f4859c0c0d15200b2060df6a3cb6a2;
+ 907dd1dff7dac5c9941d26d0c6eb14ad
+ 56
+ 9a97ebc929e438b9781ce3263e5f78f07fc74cf685c00cc7e16977985459a03d;
+ 8f86edd1dc9268eeee533285a6ed810c
+ 9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd883
+ 27ce94c2d0af1899c43ec264b5ae7ead31b2dd65f45f3fe0e95cc0ac6576f672;
+ 74d8cde8e160ad10997a21635c6d62c9
+ 269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52
+ 571b59ffd88f5aac558bf81218c3cb2fdd9e800b3326401c649e53bd5a406f57;
+ ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6
+ ""
+ 2efae48af6eabef0778e76390430974fbaaf244c3fc6bbdb1e58b13bcb580fb7;
+ c95a97a48030370c33d090c54215abd6b3ad54ef
+ c9
+ 4aee747efed92d046967d15c7fa52ad582133e03a0a177ac602ab5666e5c23cb;
+ a38378c5b93bf4f2aad2605faee2b03fb648e27f
+ ff63102758fe2b69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2
+ e5afbb13c8243b7c984eeaa0307277e7092658217292fbf05e8d0a56e3fc1b21;
+ 712a199e533fa9156308cdec3f768281e040a9b9
+ a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c4
+ 913f5198775e26d1e0f6c2a2d05e26b280f7ddcf117f19afaba1ee0da1426e70;
+ 6f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad
+ ""
+ 1f93abf128d33b355c0a88df509ac50535f22ab4fb12799f703517544aa9acb9;
+ 89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20
+ a8
+ 3f86edb2b064d7d351daf60764c151d2f8759968ece6d3f000b792f6c3c92faf;
+ f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f
+ 1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a874498ad0abe
+ 27080744f866bf654524ac485f602841ee45bda2e22542f55ebee2e275952bff;
+ f8bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784
+ e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c
+ 17313b005c8ed5153fe443e60220e8f21373fccd865532655f15d74393767da0;
+ 5ffb824173d7634c04226f30
+ ""
+ f4a17475609b3057cf1af06d015538a527b56fb849c986850c224ace1775cbab;
+ cbb7f0e4a973a8cd19010731
+ 47
+ 74a4cd7ca684aa5015445562c68f2c4dbdf63d4ac5fb0f392eaf16b533fb0304;
+ 17a77456f3ff669c732b58db
+ 8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967c0a4
+ 83b54ce5e25f2c786bf25fe30336fd71900040f048dba6e99d175ac195510fac;
+ 58cb948bdd409b687fa3a682
+ 7b480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d
+ 631ff4d45f8f6536dbc36c29a857d440c7769e87829b468e051e0de73f82940a;
+}
+
+rijndael256-ocb3 {
+ 60d7bcda163547d348b7551195e77022
+ 907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268eeee533285a6
+ ""
+ ""
+ ""
+ 94cd6ce38b3c77d05a0a0d25c295a65a6b7d7dfe954b0cefac92134d2864832b;
+ ed810c9b689daaa9060d2d4b60030623
+ 65b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c95198
+ 48
+ ""
+ ""
+ 405c363c87384173bb83480d788161af11844656e9cef376f25b82bb5e1c537f;
+ a877ff77bf79192a5b50ade5d9cd739a
+ 3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d
+ ""
+ 8f
+ 0f
+ 66d804966f42b17b54de7c5c83254b129c4ceb4a428c76c4d8d06cc3efa3108d;
+ a21f2dd88374d8cde8e160ad10997a21
+ 635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3
+ ""
+ b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a4803037
+ 874bd486ad241e305a5a00887137d77528095262228eb73fd52f1c6e6313600da01bf461d676730308c2c61feb98f1cda079b3b4372c6c3871c434c75972bb12fabfd29bb6253fc54ba1b93a30fd2bbb0d8552886c324a268afc3049aec44900
+ 5913eb9194f12a3cf55bc082c9dc16ea94539318585e88fb31cb62f6732e7004;
+ 0c33d090c54215abd6b3ad54efc9a383
+ 78c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26af
+ a3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cd
+ ec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b
+ 0ff57de3d2cc21519dd3d0f49fda28b2b5be55e284d48d36e5cba568ae1e8b58fa124c37912109af141b0f186c2fa348b62ca46c66b6889aefe7d2feb01a0379069e051ef893b2a1b40d67aa04b99c53ceda7b3bcd2b7981638e4d8a319e8283
+ 68dbfe675410e257abc994d87e0d6b3285ef039f4296e4a3ef6c3380e8b9d057;
+ 09c063c46f88de9fd41e72d7b97e23e6
+ eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e
+ ""
+ 7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c
+ c5cbe3643d4234720636c3db98390cf32199996b8ce59bc07885a360d5cfd002cdf9be271301983a242a71f966668b54deb6cc8e602c11b4db33b0ef65437bfdf4a92d0f923f9997c3c74c3d850b8a485615e0b50b07f76cb252602bf211492cc980113905
+ 5470a7b06cc51ec77c63446ca423d3153633f1957329423be3a685b42981dea2;
+ 31e6bc58c0b7cadcb658b970e47479a6
+ 84b5aefa69a4cd52147ed12ca986981a874498ad0abef8bc4fcb70e27e98
+ ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc
+ 2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0cae
+ 870e6e1f56383e064accc0744f1b450d79455adbc72e49461ba13564ccf944450db7425db27c41f82bb0a36397116c2cd1a1034920fa12bdc9d6fc62cedef298195a8e05dd34cdef1726048ee2d8c9ab7d5f46f8c9446baf704c7755f3ee8d91a6fe91b14b
+ 67d3c0473bc44d9ab3f05eb918cb7161773a63428d9d399854041d31168df643;
+ 9ce021a5f1fa4ffa91544485f1a1258b2b9b8f09
+ 11e32d65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967
+ ""
+ ""
+ ""
+ 220a303425f9a53ce13518047d3dd5d8a1d2109ac835eceb441c5a586185f99a;
+ c0a458cb948bdd409b687fa3a6827b480aa3a4c8
+ 4cef64f6c9b53bf8f957f4b03cf43e89957f9a3e8128f8743d16687b7bb8
+ de
+ ""
+ ""
+ 7c5abcd9e9323820d615abf862549cc31c1b4e1a1e4da3e5433ba6e39e5bf538;
+ b9bd205b70e04c091d205cdad9e9a79b1abf91b0
+ 851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2
+ ""
+ ec
+ a0
+ 3fce0fc48d3f0d7643ebeed0d4717eaaec3f4e2dfdff01a8785fb143e532f5a5;
+ ccb44d65bad397abfaf529ee41cf9a05c7efedef
+ 3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e
+ ""
+ 8a5718fd25014107c8e7d715a92add9589d1f5c054b2d983514605ec590294a319b9802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde957
+ 61bc90511fe93f33ef7e6ab4413c9a0316b1c5ed6f08f6b01242a31e226cf226df4af92db146356f1085cca26df2fc170b84f4b8106ecf2d83fad1572c3be1c30bdbf150035a6133b3ca54639084608bcd0aad6999675b63f2550129a01dee57
+ 3310b19ecff1df1ec1e41c327a823ad057d4f4f494a867a029f27be5f9c540c2;
+ 59ac46fee6dda7abc8ad68daac90cfe22d2f1f29
+ 68cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4563d
+ 405e51881e99027b8ab9aea3ccf860b0009740763d96836c5f87b95460938de1288c69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c36800d9645563a308ba60076817523bd2abf
+ 1261b089d8f23a9c2835076a23faac2cdd67771cc667a8331f0a170b66283e4f834a06148f302c3973accd56f6f24e33958b8c2e2352fd61e4fa8fec816ac861a8b33779f09e7a10fc02a8f48afa3080ee119a52a9a817e4f2b94b0820cab383
+ 134807254d64c7724ed92cdad040f7f59a768628d3d57c45bd3eceae504854100ec839b7c3ccac4e6644fad7812fc05834435d690b67bedb6f4801c9c4ae2d8fbfb1c879e6546e6db284071ed8ffb46ea8969dd3ca48cf3872c1a7d80ceb46c8
+ b379c41bb4390d6908cfe111a9dd6dcc768b040ffe4af315f3cef5e0aa8c86c8;
+ a8cffeea7c486315799dc875fba578c8ec483789
+ 8a92142b5b0677da1ac273117b45bcfff5d5f8b6fde2893232a9f81d1451
+ ""
+ 7ffae475f6b94a43a67b3d380d2f9aaafe2dd721c0095c8808847689211450ba8095ffab1eaadf66fd22ac1976063e113ab61f813e28a1397a7974a1d7f4220c785fe426a5a0e80f678d404147842941feeffdc2eb44dc8c0d5e8f444f7f4e0c893959b74d
+ 7b5de357d72bd4a66e08bdf26b45f5d47e4c4042b89c239682d74e9bb1cd0f544aae03e377c97b30688249beb16e2e43d82c7761d7e61ceb853ad2209c68b405e99283fac3df1c6c2dd8222a9adcfbe909f0fcd81692e36a49b04dc2b1841f26145fcf57d6
+ dd6d1166ec2c7975dcdb49e29a3d55ae62fd37726266e884efea710157757b61;
+ c23a7bb40e7e0013e5150686d2301b43a15a84e8
+ 1d7f5cedaa49e2414ebf47970e560475cff206877de69146acc3ab6cf855
+ 6b7aa776945948d1b8834df2196c92ec1718dcdeee0d52d9539726d2810391b3f9d10c39b07ae8f08ce7cee4758a386a9943e97dedfbe61e737882cd09c2b9a80f34c0fde11c2481b11fc76bfa4dbf710a9e544e0c536ca1e040f9
+ ad5b04140d98edabe08485290a4d87d13b07398a1458c2c6b61dbdbc1cccada8c1a0a9aabb6c4e3c3554f8fb1ef61614c270295dfc0ca6551ca4bdb75359f91cb9d921056b7de74fc9a9b37154ce6c0b396179d31f06a1dd5982cbc0d7cb23841da1ae8f4a
+ 8257b8b269a4660300f762471821ca7a83d067b72aba369efa0edf5900693daee8da585e8f41aacde010cb5efbec25bd2ad47c1112f5ae87f79180659f3eb86052d760392fd1a268c2e75ad6e6dc447f5581fbd2aaf41bf7120c169688c8043b3db9f8fc1c
+ 3d62bf30f4aca83ca3198e4d91e2ac40c9c6e5be1f6e02943f0a947022425d5b;
+ e480cda98ad6cf2bacf6f9fd3f821330c43f3df6c2b3fac7cbcf9652
+ 3d4723f91801325eb8553236651c96788d73d192ee53b3f3ebd66ddd98ce
+ ""
+ ""
+ ""
+ 5f89715a1b8c7fb4fd3816b482fecf863fd5ffd013258827030d840fa2d2a1d7;
+ dbe88e245de25b1593b70f8601562d90a9b59ed034a867642d25d547
+ 56fa5c47f16f64b837bb4926214211a1c696ba172010abb433922a22d9fd
+ 88
+ ""
+ ""
+ 065b3d824cbbad977cf67a74c2dcdf3605309d86ab3df633aa3ab27347e44e82;
+ 1519165eb9d85197a21cc34ac0d5ae7be8dbf98e4ffed2cf6b1372a5
+ aa47b54fd9d70c70e117bf1cae71b3a56f0e7d839ea59cc783443d64f2ed
+ ""
+ 6a
+ 69
+ 9a88da0ce1b21c5c7ca8badc6b9e8e59ed577ac39b0af14fdab20b02dc9df442;
+ 29b96856beca34fd6544bcf86b799e2a1681160ccf055f0fd3001da5
+ 97a1406d465b7b1419ea51cf858f938f6daafbd656445a09898eaa
+ ""
+ 96ffc3d1d2e31e4e34c94b8bfae64825ecd75a66d88eedb969ffe07669845ebb7a24c69f13d099f47166edf54538e88fbf433a7ff212085179e79771f6eee7283ab178ef2b800d7b969da05780ffc1ba78c70dda7a4ca2a25e771702fb1901ec
+ e3e73214e48c0326b4e390a35aa9c0d9a8696a196543c3bf9409f2675fedcb4b5b369ec744fcb5d2ee7a5e76549f1f9e2a7c98b1989349e37e82bed729c9278ef0a925fdc7c838535dfe0351f8d7b3be579c9b17382ab0720513ea9c485097c6
+ ef9f792e7eff79fb841852ed80cb6b30429520d077bbedde0d797735230dca6d;
+ fc8a959cb8e75079bb018ccc8c54f31b450e88f8e9002926ad0284c7
+ 38f4cb0f58a1e34c8b15ad930c1b627235a2cb84241986c251f5b70be2
+ 367f047265264e0da72efe8995e6c932a17eab511eddb8e4ba463c663035a6ae8a7a899e4279d54d03f0e0f3e961dcfd40088d5be74088e4097efb0368c7e2f431ee6988cf2a0e9ebeb3de79c4f86c9e4fba61339d6d907eab7707ca48ff5ba1
+ ae93d16225d469de5747bc1addf5748729720a320fe14fd29cfc59314fe2079c0a2535ded56112d6e3d33dcf7c71cd7d130323794e3da84a9df69703a9caf02d2a8f57ac71e554a6850d55882f8c7ae6994fc8528bd18c374fc43581d2f72a89
+ 17bd1896ca1775f27a78f55e568ac95360963aa799f1736346c94174b2749d9626a2d11af0a3717f4ddd4bb7d71c27c834cc11973300b851590c28bc90e377b9c672be42329e4fdc2b8178f54727f529d6c6c973ffef4bc3d829df42e2913d93
+ 0666959b0610c0e4390049ff5339e64bf450a485947e7ced421550d5b4237143;
+ 584a2404a059f7f99c7241a0c879d6d4455b382a9ce757b3e7a1d075
+ 85ad9d7ea9c7c9cf54f3bc6d94238ab56d738e02abd651477cd726d6f3eb
+ ""
+ cd6fadeab50906642a7de6496247060e7be3632ed9bd94bb42f45a8733b2cd2df9d1d905cfdb29983050d6bcdb686a0c897031ad09a5b8fa687ec3bad8e18dc2ad361f1e226e78876cd35f86c639733c5cd84aed8aaebabb7e0f24edfd9710b7bca91b612e
+ d98615675232b1e3b446b8ef49645238f92b1286e06f32a6086476e1cf2636ee4591be6c515a03f84c5f5bdbf0550ad6440e5614eea29ff878fc7a1a59292ee7076722c6c12bd0561eb01666fc0eaa74acb29400ab1af944693f08c3df1202efb9aafa5204
+ 4ebd32cea5c4e8e22ae8d025273d736a7aa4ea99ec35555379d29b64beb35275;
+ a37fc5cc09f7f62f66b423fcd2dec5de24d264f2c839839c1b06319f
+ 687dbc68d9f07fd41ccb4f8cde8de201ec2680332bbded4883deea0b58b5
+ 4bdd13c17ef292b0ded3caeb5e57fd21df10bc6186265ee6ea45907de6cb822fb2ef953aea358a03e0fce2e1b9511bd332c86e67f123377a8f0256b8dcc73ae1b3c6cd3f104e3cb24284cfed17811d64d492d39ea7496993a25b07
+ 2945d83f923e66b0a6689cf0969c003a8fca80e322a4b1bf050c1220450433efb6b6d8a2d820cf27a64b9d47f636845dac557bb3e75f3a18fb8e173416867fcd0ee78ddd9236beec76d55ed58b10f91d07a037791ab96e83c4bf2fb5b205e592c172a5cbc1
+ d9971e97c6107f5e95716634e4731360542765a84d798c706f88a6dbbe83b4d0588bbea20e927524f8d21de8ab71a910ed5bae27aaea95bd20fb05563fca2674cd6037d9fce9a1ea0f47fae536d92b837aa391a5a8f6c9b4e5280b66553d7516df90b4bed4
+ ed3bb7517af2601dd23e9c5b54c63eeb050f51d15acdaebd6bc47325ffd33ff8;
+ 9456c95c1bea6079f3867e52
+ d663cb3884b2a0a8ff825df752423f3179bfeb89eca385f20ddce5f1f235
+ ""
+ ""
+ ""
+ d7bd5a595d894ff087b4120947bda4fdeb956a41b2e9fe9152dd2071e11b0552;
+ 64672e370ffc37d400a31e8a
+ ac1d426ce10df73c5ee478b3b63d91024780e974a8a2a0e7a36f84ab1286
+ b6
+ ""
+ ""
+ affeb59e316bcec613e4ba87e80e83c1204f83e9aaba7de2263c76c1778c3c34;
+ 27e7d01b38a84a6de738721e
+ d80fd0d7f69fa658abb5a440d304128719b541a9451cead18e4c61d93d1f
+ ""
+ 8f
+ 5a
+ 92a3d896a62298b49df5d041c3f30f3ca01a387e04bcd3e4e934789fa270f485;
+ cc53574427767396322b3bf7
+ d02cec05093696cec07591ada462271b1d1519eedde0df37a330fe
+ ""
+ 8c22ebd77705917b7e32ae88f45a34a8ba3037235e19a394be4d26ce47317d8087684456b4cfc5555e925e3e7b2ebc829b2d0505ea617b0ca9531bcdb96040d39040e632d562643ccb64286303040fcaf679e914eaddc05af8843ce6a427b99a
+ 984c933c9aa7fd8536cafe98d705ee19c027a3c82e1f655b87325e8694d8982e7da50abdfdda9b9275c6aaf0dd141b8f2c4fe0d4b32d1317efccf6a1768da9d15699af7c8fc90eb6386648e098795b80380933001d47f3484b771cc6435e824a
+ 300a77fde5151a0a55110605f648e984e5c5e9c297759b420773e0198fd43de6;
+ 5dc266de31c09165237eeefe
+ 4b58cc034b9f099f04678c2a9da898b39324cd3087a651014f6796f9c4
+ 881d89e127e62221e47e57badd678d490c2f320ff8fb1c42761bd439f3e96dc0ed1d5b2169912af1a4e2c533c52ba3e8c71c23a089e231480aa63c484fb34bd522397f102cb8ecf4f64e329884fe73be257a753b38200bc23f94a079bde2dd98
+ d813655dafa15b85419d15c41a5153cce5d0e8c8702db2ba11927589678d4f7b8fcfad4818c411f15f452300903874f9a532ee46496ae753a2340af7b91f9632fc5ae71ae18b40de751ab6b6761ca16434a9935e466e11c1cb072f32a59c313d
+ ed01665286324cdff1c38648e15ed6c53f9ad08c6d830bbcda44c1a43d662b55b65a02493a13da360250c8f67d83042de2a3cd4b5ef58d6de79ab9b29377377f43b179889b2d73a2a4bda38c8018504a3e3366be90700291e7f9d676bd764661
+ 7ad70b7407fb23e1d1cd1aff53cbbd9b27b27f3d5323b2492cb700d6c336a73f;
+ ba3db646ae909a096697d9a7
+ b0556463ff1126ebc43263391424d02739d0787e804d8f1dccf6c897a8a4
+ ""
+ 8431324324041b5302ccd501b538bd03d5cb5c90d1fd3f7d2be187a787032c79ed900764ee4ce1d3fc042c084f7d8c0c48ad7d6f1eabd0fd1ec24a88f26734d5c8d92dbd873a8fe113090d401bea4d28ff49f10ff593adc258e091abd31b62dd1735158f98
+ 13c29223881fcb5ac5bcbdfed11fec190f5616ac0b9a48d7c500416887ffeceda025cd1a53cef1b43980cf4930680e43727549984acf076bddb90b889ad22a81bf371bcd9b1bcbcb8e1709cce01ae25f6bf51424b6ca9c6f54cddceff6a536df344e96d66e
+ 6a5e940b5fd47e1c52ff1d6e898c535bafb686a2b12931f0d5e4a902207c5267;
+ 765970acc6602da063aae01a
+ 2a199d3a4f37a5f062d216d2053a83b5d3a0488ab0d2df631b2892cdfcf9
+ fdd0f37de9ed67179aeae82fe00009428b297b553230a6d917fa0c1a233c9ebc8a4cba45b20543c540fc1b9dbce078b87a1534acf03897b95a3f372e9f6c5a5f2ae44a7dbce9ba43a39089de20de70d0544b5151db0a16e9769e8f
+ 2fc12c7f839fab269a0056284a697ffd4113a1cf43b5d5bdce2d86dead83f5a356e9106bedf908db61f1119f9700260ea9379cc7232184d217158fee8ca42e75614739e9007f234fbcd86b0ad8f641a0449b6d9b0f99d1cb4a57a4d6f987feb0ade90aa1d8
+ 871ec85dcb564eeb30e76fa18d1c45e6e03a34fa8d3701ae975fe8ef646e5581e70a2d7de65b92d4407925500b00443315317b26a084bb65f2c3c03377dd68c814915a3215d72c409cbbd99261b6ef8d14ddc790a7a7495c7c401ab4d4041607f3f4320eec
+ 8c4b5793f59a300f6e01ddf60ff510fb1ea408ad470064a3cfe0b1b4931e6535;
+}
+
+rijndael256-ocb3-mct {
+ 32 e6daf3cc9ccaa1b05a68b6069e290909301ba320423b3a658c9552e67486ac87;
+ 28 3cab36843515c14a36039eae083324d2ab843e04f30739848bd7bead795a6cd8;
+ 24 98706671cb1048083d2e2de4692530d8259d4ca91e6f4f995f41bc2bfb575e49;
+ 20 5f3ad3100cd757cba80500b2cb3159530cebb5b1309b89eff98daa458348119f;
+ 16 a10c36f02737879b67ae2c4447f6d25cfaaae27916b95e40d2f36a40f9127415;
+ 12 2b848a4d1f15ffa8a4937abe0bf244488eb69962143c49e942fabdc21bf05bca;
+ 8 450a06d40fbcfba4feee7f6f176364093dec3f15a4d8aadc83fe1e28909b6ecd;
+ 4 43de563ee4818834fa190764e0aeda79811ff574b26466ac17415f3289d13715;
+ 32 42adb7c35588f8c6edb4abfc97b946a1649085165c7b8c3a;
+ 28 576eaa3954cc439e98263497d95da6b5e3d8279214f574c3;
+ 24 e28807d93e721c4ee87db0e382b7fd0ef97f7ea132915bb5;
+ 20 af22f7a7675fad35eb8782c40bd3c732cb1ed35c97654f8a;
+ 16 fe9d4746e3c184b1515a327e9e928c7a46b5a0cdb283baf9;
+ 12 9171f1fd2e0453fa5b993e99a6382068b0ca625dd3f9ac39;
+ 8 16823ab82ac0c840791945b5bce210ad634c57fe5c514cf5;
+ 4 bed515eaca34486fb2e069335c780d8e7b9b77c602696d9f;
+ 32 d79599b45b8f8293aaad48235eb95a2f;
+ 28 91442e4c2c8ae92f9dc870d7c3d6e0b8;
+ 24 da99ec771ce8684f4ca7ffa5df402ded;
+ 20 0d20204adc374fa840fa585a2d3a22cd;
+ 16 c3e2fb19d84accbbc5b715ea29ef175b;
+ 12 a3643da0859091dbe415fcad234bad6e;
+ 8 ab4292dc30d15a253e5a5360032cb3ab;
+ 4 74b7cfd2fc50a48ac5fad7c8d84a27bc;
+ 32 f53f5dd16d5986d94888a702;
+ 28 69bcdf722b40237c2e8fcd71;
+ 24 67e16b822be5718b363b3ff2;
+ 20 3d6fa2dabad3337e26a72bfc;
+ 16 389907e4b3cd3d0168d0a819;
+ 12 ff40fcbbbe7a203fc704dfcd;
+ 8 c67601e9b9f58b7a464e3f47;
+ 4 d1b2695277c7c8f8a9e9573c;
+ 32 238f3b1fc1fc218c;
+ 28 0f3657da64398b7e;
+ 24 07ffed4ca9d89a19;
+ 20 248ef8ba5dd3f022;
+ 16 b081c4be1451952f;
+ 12 c6932badc879fb36;
+ 8 5f41014f77919965;
+ 4 3d613ca8abe9c4ce;
+}
0102030405060708 0102030405060708 60d04ad7c49b8ded;
100f0e0d0c0b0a090807060504030201 0102030405060708 b260740f80d2445d;
}
+
+safer-cmac {
+ bef260d7bcda163547d348b7551195e7
+ ""
+ b9f9da8b0465e894;
+ 7022907dd1dff7dac5c9941d26d0c6eb
+ 14
+ cf652451ff1ea9e1;
+ ad568f86edd1dc9268eeee533285a6ed
+ 810c9b689daaa9060d2d4b6003062365b0a54364c76c160f
+ 5056bba2984b1682;
+ 11896c4794846ecfa14a7130c9f13712
+ 0634c9519848a877ff77bf79192a5b50ade5d9
+ 2c9685d013b7efff;
+ cd739a3d1f337f29
+ ""
+ b7c678291a02ea9e;
+ 549e6b0d27a4ba23
+ 40
+ 0cb9e87774a1ef4a;
+ 85406a6136512061
+ f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a
+ 0a9d5c038c99f36d;
+ 21635c6d62c92690
+ 29df3e6057acc87638f508046733d9ff61cdbd
+ fe61dbd63946d430;
+}
+
+safer-ccm {
+ bef260d7bcda163547d348b7551195e7
+ 702290
+ ""
+ ""
+ ""
+ 74955b21;
+ 7dd1dff7dac5c9941d26d0c6eb14ad56
+ 8f86ed
+ d1
+ ""
+ ""
+ 64c48de4;
+ dc9268eeee533285a6ed810c9b689daa
+ a9060d
+ ""
+ 2d
+ fe
+ a0c2fe72;
+ 4b6003062365b0a54364c76c160f1189
+ 6c4794846e
+ cfa14a7130c9f137120634c9519848a877ff77bf79192a5b
+ 50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a
+ 0f78a0e09e9cf67419d6cec4139324f10d8b36dc7b0cc47a
+ 4495b1b7dac09ecb;
+ 6136512061f7080cc07df0591d8fa21f
+ 2dd88374d8
+ cde8e160ad10997a21635c6d62c9269029df3e
+ 6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505
+ d231d706e1a93d3f14c39ffb9b4e7d849e5daa713039d171cd99e50314
+ 1b755d09c0126620;
+ da1435dceaa7b1cc
+ 49ae1d
+ ""
+ ""
+ ""
+ cd1b5bbc;
+ 50c38201a894476b
+ 3f102b
+ 75
+ ""
+ ""
+ c2096bb2;
+ 2eb9529533966f27
+ 043eb6
+ ""
+ 21
+ 53
+ 25a20612;
+ b7f65b000961040e
+ f2f9b2fc5f
+ a450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3
+ ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54
+ 226b9bb081738ba5f6626653861db3f32832d8551f5a1b96
+ 11e255d4c06111f5;
+ efc9a38378c5b93b
+ f4f2aad260
+ 5faee2b03fb648e27fff63102758fe2b69ac26
+ afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee
+ e06ad69863c7d36838a811277e746eb2319191c405682d38ccdff9654b
+ d3160250b4828281;
+}
+
+safer-eax {
+ bef260d7bcda163547d348b7551195e7
+ ""
+ ""
+ ""
+ ""
+ 75c1da0376977c83;
+ 7022907dd1dff7dac5c9941d26d0c6eb
+ 14
+ ""
+ ""
+ ""
+ e8df12a3fceed9c1;
+ ad568f86edd1dc9268eeee533285a6ed
+ ""
+ 81
+ ""
+ ""
+ 67fd181cddef533e;
+ 0c9b689daaa9060d2d4b6003062365b0
+ ""
+ ""
+ a5
+ 30
+ b9ecf97c3093922d;
+ 4364c76c160f11896c4794846ecfa14a
+ 7130c9f137120634
+ c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f
+ 29549e6b0d27a4ba234085406a6136512061f7080cc07df0
+ fb58d0f5368ea912d10744647fe366bb418777601697e28c
+ 7ca11efe24763f77;
+ 591d8fa21f2dd88374d8cde8e160ad10
+ 997a21635c6d62
+ c9269029df3e6057acc87638f508046733d9ff
+ 61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c3
+ 8f2eaca038f7cacc19b6cbd27ee094e6a78343fcead2b02356c41697ad
+ 216152ac7b8d453f;
+ 8201a894476b3f10
+ ""
+ ""
+ ""
+ ""
+ b4d102bb91a06dbb;
+ 2b752eb952953396
+ 6f
+ ""
+ ""
+ ""
+ ebaee4aba3e18cb1;
+ 27043eb621b7f65b
+ ""
+ 00
+ ""
+ ""
+ 637a640605c9a7ff;
+ 0961040ef2f9b2fc
+ ""
+ ""
+ 5f
+ f8
+ d5bfec2d60727408;
+ a450727a9b542cde
+ 52ebfda19d0ccc52
+ 0f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090
+ c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2
+ 34969314934b38d9a462ef69cbbdb80c7cebd4e6361a5faa
+ 6f46339d37873473;
+ b03fb648e27fff63
+ 102758fe2b69ac
+ 26afa3349829b94586306fed54154f8f28523c
+ 03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563
+ 27ebc64f0dc6fea2eb465c16ddcf0fb51567e3a14eeccdcf37be2ffb0a
+ a925cad73bd83f84;
+}
+
+safer-gcm {
+ bef260d7bcda163547d348b7551195e7
+ ""
+ ""
+ ""
+ ""
+ 54d777d84bb367be;
+ 7022907dd1dff7dac5c9941d26d0c6eb
+ 14
+ ""
+ ""
+ ""
+ ee0bd152340f8fa7;
+ ad568f86edd1dc9268eeee533285a6ed
+ ""
+ 81
+ ""
+ ""
+ ef542fad7971981b;
+ 0c9b689daaa9060d2d4b6003062365b0
+ ""
+ ""
+ a5
+ 68
+ 9775c4709ae7e478;
+ 4364c76c160f11896c4794846ecfa14a
+ 7130c9f137120634
+ c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f
+ 29549e6b0d27a4ba234085406a6136512061f7080cc07df0
+ ca09cf420396beb0c928209ae8423ebaf1230ae572f41b22
+ 1f53984176941a39;
+ 591d8fa21f2dd88374d8cde8e160ad10
+ 997a2163
+ 5c6d62c9269029df3e6057
+ acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7
+ b71e6a6900bbf0745a3372bc9fb843931af8c9605701f49519b02c8c2649f8ed92
+ bbc316814a9c8ff6;
+ b1cc49ae1d50c38201a894476b3f102b
+ 752eb952953396
+ 6f27043eb621b7f65b000961040ef2f9b2fc5f
+ a450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6
+ 12f78c86a8fe1b71db510309fe43a4434a5ff6a2c4dc3bc01f0feea936
+ b3a2d8864a3eabb9;
+ c95a97a48030370c
+ ""
+ ""
+ ""
+ ""
+ f0d316bc4b69c200;
+ 33d090c54215abd6
+ b3
+ ""
+ ""
+ ""
+ 92be4864decdb6b0;
+ ad54efc9a38378c5
+ ""
+ b9
+ ""
+ ""
+ 7699b3ba70391bab;
+ 3bf4f2aad2605fae
+ ""
+ ""
+ e2
+ 2f
+ 6826c1faff7a71a4;
+ b03fb648e27fff63
+ 102758fe2b69ac26
+ afa3349829b94586306fed54154f8f28523c03d4de160015
+ 7846b710ee72807a2219bfb474fd71d891f24bb65d156325
+ 9c27bc6e00c2e0ddb8d5e399439bf477cc02f23cca50e560
+ d21750cf96e20752;
+ 9f9eb53b571ea629
+ c54d57dd
+ 2d42f70800df9fcbaca48b
+ 77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040
+ 76b11272cd887c5f6fa869e7bf52578442dd96e83b0e7cbcfdba46f67ba2ee6fc0
+ 23f48c9f5534edbf;
+ a9b9a222bd689aef
+ 66f5306ceb0c6b
+ 08ac8b0a22260c571b4a42bb8fdb233bfa6a5c
+ fb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784
+ cac8eef1be089b75a8ddb79ca8588436e6e9bac025a6d89bac100dc284
+ d41ff215540bd48c;
+}
+
+safer-ocb1 {
+ bef260d7bcda163547d348b7551195e7
+ 7022907dd1dff7da
+ ""
+ ""
+ ""
+ e2e419f8cec4dcb3;
+ c5c9941d26d0c6eb14ad568f86edd1dc
+ 9268eeee533285a6
+ ed
+ ""
+ ""
+ aba50e2dfc553b0e;
+ 810c9b689daaa9060d2d4b6003062365
+ b0a54364c76c160f
+ ""
+ 11
+ c4
+ 4586e65f8c86dd50;
+ 896c4794846ecfa14a7130c9f1371206
+ 34c9519848a877ff
+ ""
+ 77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4
+ 07f19e04df183fe463e0f8d408918e4e90d5fa7c1fcbf997
+ 8248b794a7bd1a4e;
+ ba234085406a6136512061f7080cc07d
+ f0591d8fa21f2dd8
+ 8374d8cde8e160ad10997a21635c6d62c9269029df3e6057
+ acc87638f508046733d9ff61cdbda3b3e9878731ebfedd47
+ 4f53021f22a68a8d47c855e163a27226b624dd712fab3e2a
+ ff7aaeba71e97e88;
+ 05e505da1435dceaa7b1cc49ae1d50c3
+ 8201a894476b3f10
+ ""
+ 2b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450
+ 34d295b915f6715a7aac820be272519ed925b11bf0f86145df35751dae
+ 9f185db0d5f8cc21;
+ 727a9b542cde52ebfda19d0ccc520f21
+ 5eb57bb3a4f3ebbb
+ b18ac6c95a97a48030370c33d090c54215abd6
+ b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff631027
+ 2efe1a659d7d670d28fbe822b399e07290be6934f6cec51e8eb0362c7d
+ f9c31f6c694772d0;
+ 58fe2b69ac26afa3
+ 349829b94586306f
+ ""
+ ""
+ ""
+ 88301767ee937c29;
+ ed54154f8f28523c
+ 03d4de1600157846
+ b7
+ ""
+ ""
+ e4b7676fbd808aa7;
+ 10ee72807a2219bf
+ b474fd71d891f24b
+ ""
+ b6
+ a2
+ fab55a01a7ce028e;
+ 5d1563259f9eb53b
+ 571ea629c54d57dd
+ ""
+ 2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb
+ b690481d25e3f847a804a19814c1290205ce9cbb4b61c233
+ 87e5815156bfa03b;
+ 9fc2712a199e533f
+ a9156308cdec3f76
+ 8281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22
+ 260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb
+ dc2c2adba08e9ba7418ffc99171134a1581b124c03877cd1
+ 220cc3fa8f48fdd3;
+ 3b6f5fe836813111
+ 5c037ba323fe1dc8
+ ""
+ 151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b
+ b8aefb9157f020717f5afd56802e8c489aa69a4ebbfd1a5c4e05ee4dca
+ 91762112616e9ad2;
+ 09c063c46f88de9f
+ d41e72d7b97e23e6
+ eabdff3bcd211499268878dbf30f1dad89d4b9
+ b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f08345
+ 236430169ce67a46cf7a2b31e20aff1d656863550b2cbed9feb213bebd
+ 641bc761257b4572;
+}
+
+safer-pmac1 {
+ bef260d7bcda163547d348b7551195e7
+ ""
+ 061d742fa0b5e9fb;
+ 7022907dd1dff7dac5c9941d26d0c6eb
+ 14
+ 496f756150b24f97;
+ ad568f86edd1dc9268eeee533285a6ed
+ 810c9b689daaa9060d2d4b6003062365b0a54364c76c160f
+ 659f6109ebea03e4;
+ 11896c4794846ecfa14a7130c9f13712
+ 0634c9519848a877ff77bf79192a5b50ade5d9
+ 169f91020e2bfa02;
+ cd739a3d1f337f29
+ ""
+ bcb4bfd69665cfac;
+ 549e6b0d27a4ba23
+ 40
+ 1e041b274662fca9;
+ 85406a6136512061
+ f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a
+ 8b6e6d10707bb048;
+ 21635c6d62c92690
+ 29df3e6057acc87638f508046733d9ff61cdbd
+ 8ca64eea215c495b;
+}
+
+safer-ocb3 {
+ bef260d7bcda163547d348b7551195e7
+ 7022907dd1df
+ ""
+ ""
+ ""
+ c68d1906e4ecf5b7;
+ f7dac5c9941d26d0c6eb14ad568f86ed
+ d1dc9268eeee
+ 53
+ ""
+ ""
+ 3d2c6b8d272ad1bd;
+ 3285a6ed810c9b689daaa9060d2d4b60
+ 03062365b0a5
+ ""
+ 43
+ 1e
+ ac7b2f4dcf701c36;
+ 64c76c160f11896c4794846ecfa14a71
+ 30c9f1
+ ""
+ 37120634c9519848a877ff77bf79192a5b50ade5d9cd739a
+ 3d77279a2b3174b4cda74767a200b3ced178c630f4021f95
+ 46868129219846b1;
+ 3d1f337f29549e6b0d27a4ba23408540
+ 6a61365120
+ 61f7080cc07df0591d8fa21f2dd88374d8cde8e160ad1099
+ 7a21635c6d62c9269029df3e6057acc87638f508046733d9
+ 73f22628de757cf0ae4533014abe1e212cac8e7dc8d6c704
+ b0592f0672c25ce4;
+ ff61cdbda3b3e9878731ebfedd4705e5
+ 05da1435dcea
+ ""
+ a7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb6
+ 14072ae825472e9f41b4d3608dcb28f76c38dba433fac5ac21885d3590
+ 70c90062488d754e;
+ 21b7f65b000961040ef2f9b2fc5fa450
+ 727a9b542cde
+ 52ebfda19d0ccc520f215eb57bb3a4f3ebbbb1
+ 8ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93b
+ c67a74b2d9ab0e76d4e12ca3f67a21b36b96f6e153876245f24fb860d4
+ da1bc80ce1be6ab3;
+ f4f2aad2605faee2
+ b03fb648e27f
+ ""
+ ""
+ ""
+ 5c58fc2737aa84b2;
+ ff63102758fe2b69
+ ac26afa33498
+ 29
+ ""
+ ""
+ 105063844d7b9bae;
+ b94586306fed5415
+ 4f8f28523c03
+ ""
+ d4
+ 0a
+ bf73c757de4bdf7b;
+ de1600157846b710
+ ee7280
+ ""
+ 7a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea6
+ 930c7d41a8b6f15ef14b066dc63cdddb1be6e934551bd1c1
+ e40d324516b9b127;
+ 29c54d57dd2d42f7
+ 0800df9fcb
+ aca48b77dba189196d1ebba10b0467cb9fc2712a199e533f
+ a9156308cdec3f768281e040a9b9a222bd689aef66f5306c
+ 1d2eb8f21e5e62392ffee6754fba853ce71e10ac506c9e4d
+ 57dec2089ee8cd44;
+ eb0c6b08ac8b0a22
+ 260c571b4a42
+ ""
+ bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037b
+ 1cd78bee247725a186a54ff71232b3197dbad5c69ea23db3dac003d3f6
+ 3d21f3e8ffca5e4d;
+ a323fe1dc8151784
+ 873f0eb5b647
+ da6794c18b5337685a96ed65b9aca338527ef1
+ 9b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878db
+ 59da4376f65bf4bfdf59cca15597d76b021a759e71d20b382f587e1a74
+ ff7e706dfb3aadc7;
+}
+
+safer-ocb3-mct {
+ 16 fcbfdf66d89efaa3;
+ 8 7acb5078112677aa;
+ 16 baa9bc81de93;
+ 8 ca467bdf7b39;
+ 16 f6659aeb;
+ 8 1b3348ec;
+}
-### No tests here. See `safer' instead.
+### Only modes here. See `safersk' for the blockcipher test vectors.
+
+safersk-cmac {
+ bef260d7bcda163547d348b7551195e7
+ ""
+ 9ba8f2c1b6cfeb77;
+ 7022907dd1dff7dac5c9941d26d0c6eb
+ 14
+ 37dcfeffa9f5744b;
+ ad568f86edd1dc9268eeee533285a6ed
+ 810c9b689daaa9060d2d4b6003062365b0a54364c76c160f
+ 05bf5b261fbd88de;
+ 11896c4794846ecfa14a7130c9f13712
+ 0634c9519848a877ff77bf79192a5b50ade5d9
+ 0ee50cf1eb23cc77;
+ cd739a3d1f337f29
+ ""
+ 975807086410e7e5;
+ 549e6b0d27a4ba23
+ 40
+ b5b26235e6a34f78;
+ 85406a6136512061
+ f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a
+ b98cae59f10f22cd;
+ 21635c6d62c92690
+ 29df3e6057acc87638f508046733d9ff61cdbd
+ d85e3e89ce01118c;
+}
+
+safersk-ccm {
+ bef260d7bcda163547d348b7551195e7
+ 702290
+ ""
+ ""
+ ""
+ 9a4a828c;
+ 7dd1dff7dac5c9941d26d0c6eb14ad56
+ 8f86ed
+ d1
+ ""
+ ""
+ 41f68f45;
+ dc9268eeee533285a6ed810c9b689daa
+ a9060d
+ ""
+ 2d
+ 7b
+ acc985bb;
+ 4b6003062365b0a54364c76c160f1189
+ 6c4794846e
+ cfa14a7130c9f137120634c9519848a877ff77bf79192a5b
+ 50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a
+ aa629c01eb3b15ede6c2e4366419b5e5f40469d538d373ed
+ a136e047cf4a68b0;
+ 6136512061f7080cc07df0591d8fa21f
+ 2dd88374d8
+ cde8e160ad10997a21635c6d62c9269029df3e
+ 6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505
+ 1c34203b3161577c889c9db08bf34b20a3e5da5857a94d09e73edf7210
+ 953f9c31334dfede;
+ da1435dceaa7b1cc
+ 49ae1d
+ ""
+ ""
+ ""
+ b5ad4f52;
+ 50c38201a894476b
+ 3f102b
+ 75
+ ""
+ ""
+ f69a75fd;
+ 2eb9529533966f27
+ 043eb6
+ ""
+ 21
+ 14
+ 72b85363;
+ b7f65b000961040e
+ f2f9b2fc5f
+ a450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3
+ ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54
+ b65cbf23154b9798e5250e96f51659df1024bf6b0ffd859b
+ 9616166b0ae5320f;
+ efc9a38378c5b93b
+ f4f2aad260
+ 5faee2b03fb648e27fff63102758fe2b69ac26
+ afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee
+ 6d0ac961eed6fa2cad9f51d293bad02ecc7a8effe3511cb9aae4935bbd
+ 96dee0d7ba957d24;
+}
+
+safersk-eax {
+ bef260d7bcda163547d348b7551195e7
+ ""
+ ""
+ ""
+ ""
+ 9bc0cb5650ecbe0d;
+ 7022907dd1dff7dac5c9941d26d0c6eb
+ 14
+ ""
+ ""
+ ""
+ 04655ac860f00c4c;
+ ad568f86edd1dc9268eeee533285a6ed
+ ""
+ 81
+ ""
+ ""
+ 23de91600ff46611;
+ 0c9b689daaa9060d2d4b6003062365b0
+ ""
+ ""
+ a5
+ c2
+ a47b7c287e2aaccb;
+ 4364c76c160f11896c4794846ecfa14a
+ 7130c9f137120634
+ c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f
+ 29549e6b0d27a4ba234085406a6136512061f7080cc07df0
+ d228821b771c225b34c32f1d8def6b1638a580259d14966c
+ c2d9f9bcacbf1796;
+ 591d8fa21f2dd88374d8cde8e160ad10
+ 997a21635c6d62
+ c9269029df3e6057acc87638f508046733d9ff
+ 61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c3
+ 56e9c63e94a3e304fb0204a14ddce527063e43cbb59e5f4cdc5ca4c9fd
+ 3c18c6748c8d3efb;
+ 8201a894476b3f10
+ ""
+ ""
+ ""
+ ""
+ a30a7f2fdcfd304f;
+ 2b752eb952953396
+ 6f
+ ""
+ ""
+ ""
+ a3921ada1effe4a9;
+ 27043eb621b7f65b
+ ""
+ 00
+ ""
+ ""
+ b21c194c92a0e99a;
+ 0961040ef2f9b2fc
+ ""
+ ""
+ 5f
+ 9a
+ ec1dc651cd6f903d;
+ a450727a9b542cde
+ 52ebfda19d0ccc52
+ 0f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090
+ c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2
+ 74b140592d02d6e569a0f917fd935c2c4ff50e612a765163
+ 69c737214ba7d4ef;
+ b03fb648e27fff63
+ 102758fe2b69ac
+ 26afa3349829b94586306fed54154f8f28523c
+ 03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563
+ bde1b3e1c19bb966ee531fa15ec929593e29aca538a004e1a98e6776f2
+ ed2e0c47042a787f;
+}
+
+safersk-gcm {
+ bef260d7bcda163547d348b7551195e7
+ ""
+ ""
+ ""
+ ""
+ 27b0cf2d5823652b;
+ 7022907dd1dff7dac5c9941d26d0c6eb
+ 14
+ ""
+ ""
+ ""
+ 284a84e5a061c638;
+ ad568f86edd1dc9268eeee533285a6ed
+ ""
+ 81
+ ""
+ ""
+ e137081a8189b00d;
+ 0c9b689daaa9060d2d4b6003062365b0
+ ""
+ ""
+ a5
+ 07
+ d1476d790c73fe20;
+ 4364c76c160f11896c4794846ecfa14a
+ 7130c9f137120634
+ c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f
+ 29549e6b0d27a4ba234085406a6136512061f7080cc07df0
+ 220e383555bc3c1db79dd7946ab1bcfb0c8ae7534e054dfe
+ b9125ab89a341129;
+ 591d8fa21f2dd88374d8cde8e160ad10
+ 997a2163
+ 5c6d62c9269029df3e6057
+ acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7
+ da40ac7ce7efbc6e5a0c8edad1fc6e37707dcd577c2b525173d91c0ee1843bf296
+ 7fe1bd570ff9bc5e;
+ b1cc49ae1d50c38201a894476b3f102b
+ 752eb952953396
+ 6f27043eb621b7f65b000961040ef2f9b2fc5f
+ a450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6
+ 7088301eaa71ebd8aa7357fa70408eff7803127fdaf86f8f64fc46bde4
+ 1b6b05d79e3e8a50;
+ c95a97a48030370c
+ ""
+ ""
+ ""
+ ""
+ c202c8435d5db9f9;
+ 33d090c54215abd6
+ b3
+ ""
+ ""
+ ""
+ 127f007760bb2caa;
+ ad54efc9a38378c5
+ ""
+ b9
+ ""
+ ""
+ 8e7eb7606063486c;
+ 3bf4f2aad2605fae
+ ""
+ ""
+ e2
+ 87
+ f7db784dd6349ec3;
+ b03fb648e27fff63
+ 102758fe2b69ac26
+ afa3349829b94586306fed54154f8f28523c03d4de160015
+ 7846b710ee72807a2219bfb474fd71d891f24bb65d156325
+ e9a1e4e745d37146bd75efe05e451dbf120fe907a9f5701f
+ 59283c69e487ac87;
+ 9f9eb53b571ea629
+ c54d57dd
+ 2d42f70800df9fcbaca48b
+ 77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040
+ 65b78f763a328655662a4ef7f9bacfe67e5e07df80edbcc853440ee1f7627d0355
+ 38dbad9c5138e19e;
+ a9b9a222bd689aef
+ 66f5306ceb0c6b
+ 08ac8b0a22260c571b4a42bb8fdb233bfa6a5c
+ fb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784
+ 0d4082f666ad6a4d337a93564bc648f4b09e2332d656aeebefd722a7ec
+ 4322ea279fd752dc;
+}
+
+safersk-ocb1 {
+ bef260d7bcda163547d348b7551195e7
+ 7022907dd1dff7da
+ ""
+ ""
+ ""
+ 02524b8ee7329780;
+ c5c9941d26d0c6eb14ad568f86edd1dc
+ 9268eeee533285a6
+ ed
+ ""
+ ""
+ aa1f6928e1b81e20;
+ 810c9b689daaa9060d2d4b6003062365
+ b0a54364c76c160f
+ ""
+ 11
+ 07
+ cc863f9f86e79df5;
+ 896c4794846ecfa14a7130c9f1371206
+ 34c9519848a877ff
+ ""
+ 77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4
+ 0a622ec626cf3be0c96a8fcabfa824949c81cf57656e3fcc
+ 4b897d5463f508df;
+ ba234085406a6136512061f7080cc07d
+ f0591d8fa21f2dd8
+ 8374d8cde8e160ad10997a21635c6d62c9269029df3e6057
+ acc87638f508046733d9ff61cdbda3b3e9878731ebfedd47
+ ceaa0608044abe172e762b8a66a026b6aa231a60e32b8852
+ 383b6f426f78e95d;
+ 05e505da1435dceaa7b1cc49ae1d50c3
+ 8201a894476b3f10
+ ""
+ 2b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450
+ e9d6111a98647e1da68ba0bdfb386b3575c20aba3fff9bb7d5e52e5717
+ f432ded708b7e826;
+ 727a9b542cde52ebfda19d0ccc520f21
+ 5eb57bb3a4f3ebbb
+ b18ac6c95a97a48030370c33d090c54215abd6
+ b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff631027
+ 58a7612db1435cc3b8b7ab586fd3475674faa6192c47cf940061b38ad0
+ ee64360a85eb7957;
+ 58fe2b69ac26afa3
+ 349829b94586306f
+ ""
+ ""
+ ""
+ bffcea16dd9830d2;
+ ed54154f8f28523c
+ 03d4de1600157846
+ b7
+ ""
+ ""
+ 9d9d3268ed1e6af0;
+ 10ee72807a2219bf
+ b474fd71d891f24b
+ ""
+ b6
+ 55
+ 7cc85e98d653ac98;
+ 5d1563259f9eb53b
+ 571ea629c54d57dd
+ ""
+ 2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb
+ 69fd708caa761fa04396ba9f94bb916e5a11679b3bad9cf0
+ 8c94cf5b2249afa6;
+ 9fc2712a199e533f
+ a9156308cdec3f76
+ 8281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22
+ 260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb
+ c9e3275788dcac045ae1478a44aac8061f02bc7e56e516cc
+ 8adfde6b3cd647c5;
+ 3b6f5fe836813111
+ 5c037ba323fe1dc8
+ ""
+ 151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b
+ f1493455c6ef6dfb73ba4b35b25ecef1d967614169fd0db3162575f20c
+ 533087817a013891;
+ 09c063c46f88de9f
+ d41e72d7b97e23e6
+ eabdff3bcd211499268878dbf30f1dad89d4b9
+ b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f08345
+ f89081f88fa58ddd7f1974ffc3fb676fc8855e74c7b85d6e308e2c3096
+ b0c2845962f040ff;
+}
+
+safersk-pmac1 {
+ bef260d7bcda163547d348b7551195e7
+ ""
+ 6dd75ab7922413b1;
+ 7022907dd1dff7dac5c9941d26d0c6eb
+ 14
+ 7f4d03871ad27bda;
+ ad568f86edd1dc9268eeee533285a6ed
+ 810c9b689daaa9060d2d4b6003062365b0a54364c76c160f
+ 3f48cfbe20527417;
+ 11896c4794846ecfa14a7130c9f13712
+ 0634c9519848a877ff77bf79192a5b50ade5d9
+ 25fb410e71c6553d;
+ cd739a3d1f337f29
+ ""
+ af55847d75152f93;
+ 549e6b0d27a4ba23
+ 40
+ b24dc9bbdbe4b417;
+ 85406a6136512061
+ f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a
+ 9e119f41d7bf7b13;
+ 21635c6d62c92690
+ 29df3e6057acc87638f508046733d9ff61cdbd
+ 9f8f71cddf2bf6dd;
+}
+
+safersk-ocb3 {
+ bef260d7bcda163547d348b7551195e7
+ 7022907dd1df
+ ""
+ ""
+ ""
+ 6e456312a40d6780;
+ f7dac5c9941d26d0c6eb14ad568f86ed
+ d1dc9268eeee
+ 53
+ ""
+ ""
+ 65b5cb090a3f28ae;
+ 3285a6ed810c9b689daaa9060d2d4b60
+ 03062365b0a5
+ ""
+ 43
+ 63
+ 4e6dc1b24486771b;
+ 64c76c160f11896c4794846ecfa14a71
+ 30c9f1
+ ""
+ 37120634c9519848a877ff77bf79192a5b50ade5d9cd739a
+ fa8d42d4d17056a5cb34c6792272af358e3c7e7b9490aa3f
+ 3acb963aa0fc701f;
+ 3d1f337f29549e6b0d27a4ba23408540
+ 6a61365120
+ 61f7080cc07df0591d8fa21f2dd88374d8cde8e160ad1099
+ 7a21635c6d62c9269029df3e6057acc87638f508046733d9
+ 8cd70cce2aaf4a9ea62faa31d7146087d2b9b47e7992e17e
+ 3e16cf32a2faa211;
+ ff61cdbda3b3e9878731ebfedd4705e5
+ 05da1435dcea
+ ""
+ a7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb6
+ 239d7c4c0f2c17577768de8cbedf192d08e82cfc74a587ab5267ee7e81
+ e6f7aad35cceb122;
+ 21b7f65b000961040ef2f9b2fc5fa450
+ 727a9b542cde
+ 52ebfda19d0ccc520f215eb57bb3a4f3ebbbb1
+ 8ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93b
+ bbd3b140decdd5e0a63b4a38989e770bedbe26054f882cbf1920fbd514
+ a71d070227d87267;
+ f4f2aad2605faee2
+ b03fb648e27f
+ ""
+ ""
+ ""
+ 63e4d0211e0a4daf;
+ ff63102758fe2b69
+ ac26afa33498
+ 29
+ ""
+ ""
+ 0fb3f4a5cc43406a;
+ b94586306fed5415
+ 4f8f28523c03
+ ""
+ d4
+ 06
+ afaa82d25e44d4db;
+ de1600157846b710
+ ee7280
+ ""
+ 7a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea6
+ bc640b0230973b8be088cdc0f0c18fafe95f13d3197d9c09
+ e42c5b6c0e33d57e;
+ 29c54d57dd2d42f7
+ 0800df9fcb
+ aca48b77dba189196d1ebba10b0467cb9fc2712a199e533f
+ a9156308cdec3f768281e040a9b9a222bd689aef66f5306c
+ f9f9760a9b9277c4216a7d12c59d78f7cfc3c5fe811f9e38
+ 26bd0ba14ccc28d3;
+ eb0c6b08ac8b0a22
+ 260c571b4a42
+ ""
+ bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037b
+ 35511a69e4039fa87bf9cccdd152453842004258de53166380645f0c57
+ 99979d46633f3381;
+ a323fe1dc8151784
+ 873f0eb5b647
+ da6794c18b5337685a96ed65b9aca338527ef1
+ 9b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878db
+ b6190f6df6109cb3134a517871e360503ace233210255bd503451ccf78
+ b9d9982e2ad6564b;
+}
+
+safersk-ocb3-mct {
+ 16 3857e95d746bbe01;
+ 8 545057df78fb5ea9;
+ 16 c2e0438d09ff;
+ 8 36b5c340bd6d;
+ 16 5dee93a9;
+ 8 8752f8e9;
+}
be075fc53c81f2d5cf141316ebeb0c7b5228c52a4c62cbd44b66849b64244ffce5ecbaaf33bd751a1ac728d45e6c61296cdc3c01233561f41db66cce314adb310e3be8250c46f06dceea3a7fa1348057e2f6556ad6b1318a024a838f21af1fde048977eb48f59ffd4924ca1c60902e52f0a089bc76897040e082f937763848645e0705
8e993b9f48681273c29650ba32fc76ce48332ea7164d96a4476fb8c531a1186ac0dfc17c98dce87b4da7f011ec48c97271d2c20f9b928fe2270d6fb863d51738b48eeee314a7cc8ab932164548e526ae90224368517acfeabd6bb3732bc0e9da99832b61ca01b6de56244a9e88d5f9b37973f622a43d14a6599b1f654cb45a74e355a5;
}
+
+salsa20-naclbox {
+ ## Taken from Daniel J. Bernstein, `Cryptography in NaCl',
+ ## https://cr.yp.to/highspeed/naclcrypto-20090310.pdf
+
+ 1b27556473e985d462cd51197a9a46c76009549eac6474f206c4ee0844f68389
+ 69696ee955b62b73cd62bda875fc73d68219e0036b7a0b37
+ ""
+ be075fc53c81f2d5cf141316ebeb0c7b5228c52a4c62cbd44b66849b64244ffce5ecbaaf33bd751a1ac728d45e6c61296cdc3c01233561f41db66cce314adb310e3be8250c46f06dceea3a7fa1348057e2f6556ad6b1318a024a838f21af1fde048977eb48f59ffd4924ca1c60902e52f0a089bc76897040e082f937763848645e0705
+ 8e993b9f48681273c29650ba32fc76ce48332ea7164d96a4476fb8c531a1186ac0dfc17c98dce87b4da7f011ec48c97271d2c20f9b928fe2270d6fb863d51738b48eeee314a7cc8ab932164548e526ae90224368517acfeabd6bb3732bc0e9da99832b61ca01b6de56244a9e88d5f9b37973f622a43d14a6599b1f654cb45a74e355a5
+ f3ffc7703f9400e52a7dfb4b3d3305d9;
+}
--- /dev/null
+### Local tests for Serpent.
+
+serpent-cmac {
+ 60d7bcda163547d348b7551195
+ ""
+ 837d499a07a2518f04835f42131f5831;
+ e77022907dd1dff7dac5c9941d
+ 26
+ db320e0bfa3ebb37c57ea0c60576c393;
+ d0c6eb14ad568f86edd1dc9268
+ eeee533285a6ed810c9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f1371206
+ 0c9a89126f4cad2192ffa4a7c0ca9d68;
+ 34c9519848a877ff77bf79192a
+ 5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd8
+ 324c00f44175151d1a2bf9342cf4ef93;
+ 8374d8cde8e160ad10997a21
+ ""
+ 829328f2a128fdc7c48a7714a5f66acf;
+ 635c6d62c9269029df3e6057
+ ac
+ 28d493c79ae17e3c1480c921bf4e6d2e;
+ c87638f508046733d9ff61cd
+ bda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb6
+ 63c9c5f2dcd9e476c72dee514b84d6f9;
+ 21b7f65b000961040ef2f9b2
+ fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c5
+ ca4332a12b4981383e8548d4beacce63;
+ 4215abd6b3ad54ef
+ ""
+ 51a036a675d7fd48aea66b5fea454712;
+ c9a38378c5b93bf4
+ f2
+ 5b8642963edfd3fc3537cf7a53ffdb72;
+ aad2605faee2b03f
+ b648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219
+ 40bbb9860714b5c28a127928704b04f2;
+ bfb474fd71d891f2
+ 4bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9f
+ b59d4d54d7846d564c8e65a6ae652a74;
+ c2712a199e533fa9156308cdec3f768281
+ ""
+ 9af557733264840dca5e8260f160ffb4;
+ e040a9b9a222bd689aef66f5306ceb0c6b
+ 08
+ ca7d2919e279fd3caf61e6ff35bb7803;
+ ac8b0a22260c571b4a42bb8fdb233bfa6a
+ 5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65
+ 33036f52f479780af315c2de95e9dc86;
+ b9aca338527ef19b09c063c46f88de9fd4
+ 1e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d
+ 8ef0d030ddb7bd4c700e15efc563f5cf;
+}
+
+serpent-ccm {
+ 60d7bcda163547d348b7551195
+ e77022907dd1dff7dac5c9
+ ""
+ ""
+ ""
+ dc912161;
+ 941d26d0c6eb14ad568f86edd1
+ dc9268eeee533285a6ed81
+ 0c
+ ""
+ ""
+ 5499b369;
+ 9b689daaa9060d2d4b60030623
+ 65b0a54364c76c160f1189
+ ""
+ 6c
+ 52
+ ea1be4b3;
+ 4794846ecfa14a7130c9f13712
+ 0634c9519848a877ff
+ 77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd8
+ 8374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd47
+ 1d58fa7d358e6d619c942eb0285e79dbce0aee4e671ef19021d80ece2710a144ae511c8f973ff2f06d8c6f0cc2942c5e
+ 18d3a010e72c36fd75d6c2379c947385;
+ 05e505da1435dceaa7b1cc49ae
+ 1d50c38201a894476b
+ 3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0c
+ cc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb6
+ 7b48d588bb1af8f0eff0e80c692d51010b7f3b1d6655b2e18c1241862819d1a25631053d5eea17417a5b5c928d32eb181043df7dde
+ 8e0224854ea7153f52e096633776fc97;
+ 48e27fff63102758fe2b69ac
+ 26afa3349829b94586306f
+ ""
+ ""
+ ""
+ 940a7ecd;
+ ed54154f8f28523c03d4de16
+ 00157846b710ee72807a22
+ 19
+ ""
+ ""
+ 99081a6e;
+ bfb474fd71d891f24bb65d15
+ 63259f9eb53b571ea629c5
+ ""
+ 4d
+ 95
+ 67001f0c;
+ 57dd2d42f70800df9fcbaca4
+ 8b77dba189196d1ebb
+ a10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c57
+ 1b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da67
+ 59c14232f48220ad1f3966d9d52d9b9b9ae739c4fa6a690c445716eb73951b229de71b78e83b03ac3401f58adaafd1bd
+ 2f3304e936c26f3998308ceb36022d3a;
+ 94c18b5337685a96ed65b9ac
+ a338527ef19b09c063
+ c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e
+ 7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d079839180
+ 99574f4879d83e020a18b5133a5c97d0c7fc72a37e787d16e6d8e959df0cc8d9b62cb8f54d74208c140f13abce1dc058829dc0bd01
+ 0dd232275c64fcfc8b5d0fc2bf948ebe;
+ 5da08da3aefc5f85
+ 84b7c5e617669c0f16e398
+ ""
+ ""
+ ""
+ e6725fe0;
+ 15d4e9cfce3ed1ec
+ df3d264a7f16cb16c2e815
+ f4
+ ""
+ ""
+ ad7b2fe0;
+ 22cdf0c8e30308be
+ 3c31e6bc58c0b7cadcb658
+ ""
+ b9
+ 6e
+ f2943ec1;
+ 70e47479a684b5ae
+ fa69a4cd52147ed12c
+ a986981a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae98
+ 5511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608
+ e1e63326b5795e04360ba24658defb1216302976c9a921ea18adf8b1723a91a6a8095e1d2b49a9e48cd603dd707d881e
+ 1b69dccc1f344f1ca9d04a725b5481bc;
+ fe95e81c2533e31c
+ 9c1a9851bc2810d858
+ cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717a7
+ 7456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0c
+ 61ad6fd5019e1229ae86cd9840357861473a647ec3a939e9e68113c289e1f917e658651cf2217aa46837c404632b1feabb16939df0
+ 6881e216ee5fd2da76529e9019027188;
+ ae9ce021a5f1fa4ffa91544485f1a1258b
+ 2b9b8f0911e32d65cc1770
+ ""
+ ""
+ ""
+ 6679e4e9;
+ a18cbfe6effd1ff6778554acf1270485b2
+ 03a3c1c4c967c0a458cb94
+ 8b
+ ""
+ ""
+ c6460f74;
+ dd409b687fa3a6827b480aa3a4c84cef64
+ f6c9b53bf8f957f4b03cf4
+ ""
+ 3e
+ 83
+ b85403e7;
+ 89957f9a3e8128f8743d16687b7bb8deb9
+ bd205b70e04c091d20
+ 5cdad9e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397
+ abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a5718fd25014107
+ 2651fec0d8fcff49d1f5df59bf41bd0c6fef0e7d49c915bd20f775ffd8af47be58f20ed9f7a5709978e5af892ff52ea6
+ 8247a18e44f3a38840a6c98db85a10e3;
+ c8e7d715a92add9589d1f5c054b2d98351
+ 4605ec590294a319b9
+ 802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe079753ee
+ 1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44
+ f060d6a432737be40681731d964ae4310460967fab931db70fd394d02c4f2691b14891986837af0342d9d01e688498e161ce84598a
+ 6db772689af25f8ebba8ad1966dfa1ea;
+}
+
+serpent-eax {
+ ## Taken from Secnet, with thanks to Ian Jackson.
+
+ 233952dee4d5ed5f9b9c6d6ff80ff478
+ 62ec67f9c3a4a407fcb2a8c49031a8b3
+ 6bfb914fd07eae6b
+ ""
+ ""
+ 1271ec1e68330eb461a96d3a3a7a2707;
+ 91945d3f4dcbee0bf45ef52255f095a4
+ becaf043b0a23d843194ba972c66debd
+ fa3bfd4806eb53fa
+ f7fb
+ 1c73
+ 67d3db493a1f7b054ececa2a2cf37ee6;
+ 01f74ad64077f2e704c0f60ada3dd523
+ 70c3db4f0d26368400a10ed05d2bff5e
+ 234a3463c1264ac6
+ 1a47cb4933
+ 2439712b59
+ b13982351ba05b25bb2bd3b95df62d73;
+ d07cf6cbb7f313bdde66b727afd3c5e8
+ 8408dfff3c1a2b1292dc199e46b7d617
+ 33cce2eabff5a79d
+ 481c9e39b1
+ f1d718884b
+ e94b29e143a264b54e283ca9e439c90d;
+ 35b6d0580005bbc12b0587124557d2c2
+ fdb6b06676eedc5c61d74276e1f8e816
+ aeb96eaebe2970e9
+ 40d0c07da5e4
+ 5936db85df31
+ 199ba3556a5d5eff1964a6befea0d950;
+ bd8e6e11475e60b268784c38c62feb22
+ 6eac5c93072d8e8513f750935e46da1b
+ d4482d1ca78dce0f
+ 4de3b35c3fc039245bd1fb7d
+ 7a3a7997ee349b57152cc43f
+ 723903a85b09d86456315ac0d9180724;
+ 7c77d6e813bed5ac98baa417477a2e7d
+ 1a8c98dcd73d38393b2bf1569deefc19
+ 65d2017990d62528
+ 8b0a79306c9ce7ed99dae4f87f8dd61636
+ 73548ffaf45d2617eb25ad1dffa1842083
+ 6d48394d5ef2cd2e0e30cdd2f4c52d96;
+ 5fff20cafab119ca2fc73549e20f5b0d
+ dde59b97d722156d4d9aff2bc7559826
+ 54b9f04e6a09189a
+ 1bda122bce8a8dbaf1877d962b8592dd2d56
+ e8bd1c6fe47df149a141ce813b0c1239542e
+ c4cbf7b3968388d631e6f4ffe86e14e7;
+ a4a4782bcffd3ec5e7ef6d8c34a56123
+ b781fcf2f75fa5a8de97a9ca48e522ec
+ 899a175897561d7e
+ 6cf36720872b8513f6eab1a8a44438d5ef11
+ e4a9d72847d437b85f10b7daa46f1e00e350
+ 9af0b97961c39dfbb70170b6c4cadbc1;
+ 8395fcf1e95bebd697bd010bc766aac3
+ 22e7add93cfc6393c57ec0b3c17d6b44
+ 126735fcc320d25a
+ ca40d7446e545ffaed3bd12a740a659ffbbb3ceab7
+ 83d69403eae9386b679daeaad2951465f8ddf9be1a
+ ffad1c5fef072f8b48bd58c07fee3d83;
+
+ ## Locally-generated tests for edge-cases.
+ 60d7bcda163547d348b7551195
+ ""
+ ""
+ ""
+ ""
+ 47f4f974dac8fbccb2d85c4dd030ecc2;
+ e77022907dd1dff7dac5c9941d
+ 26
+ ""
+ ""
+ ""
+ fdd1a67df6ef4962c0e07c3bcb258fdb;
+ d0c6eb14ad568f86edd1dc9268
+ ""
+ ee
+ ""
+ ""
+ dddced0e626e1a606ad6150f981231c4;
+ ee533285a6ed810c9b689daaa9
+ ""
+ ""
+ 06
+ 93
+ 994b5c972bc7d85771220863405b62be;
+ 0d2d4b6003062365b0a54364c7
+ 6c160f11896c4794846ecfa14a7130c9
+ f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7
+ 080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61
+ 82f5aab367d2f92bb06cdbdcf3b840fa03775f8473bc2c7923d06b0d264679c2bb8ad3a0b4008946198caa858ac3035b
+ 4be2dd26de2bb142d08d2e80ff7e1556;
+ cdbda3b3e9878731ebfedd4705
+ e505da1435dceaa7b1cc49ae1d50c3
+ 8201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde
+ 52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad260
+ 4a2f0f21a4c240fcebbda1500c1c87193c1100ab9922b6c02b6200eb6c4c166ba715f09ba95ff7daa0a49a92139b1fb7785198c3cd
+ 7597b3928b3811ad02ba9c380fc053b7;
+ 5faee2b03fb648e27fff6310
+ ""
+ ""
+ ""
+ ""
+ 0a85bbdf824c6fd51bb56934219a44bb;
+ 2758fe2b69ac26afa3349829
+ b9
+ ""
+ ""
+ ""
+ 8b3c4c5ef77b2b25cd78f8e7ee1a1eeb;
+ 4586306fed54154f8f28523c
+ ""
+ 03
+ ""
+ ""
+ 9dd8b376a786caa020f631ec33e8adee;
+ d4de1600157846b710ee7280
+ ""
+ ""
+ 7a
+ 9d
+ 66d221c6542adab014cde389a8375271;
+ 2219bfb474fd71d891f24bb6
+ 5d1563259f9eb53b571ea629c54d57dd
+ 2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222
+ bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe836813111
+ d70c3fe1525edf6975dd3ec110f44d66ee38812bee278632cd476e9571d90ea3a4181e472841e699acbb613172b3c8d9
+ cf949b9623f6027249246ff3914f4c9e;
+ 5c037ba323fe1dc815178487
+ 3f0eb5b647da6794c18b5337685a96
+ ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89
+ d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d
+ bbeb0d455e42b31743e6b1f62e7a8beb05b6579140f9523b441f1523fffd56799ea74a815f64cd65fe2d912c0ac88a42d668020ad4
+ aa19b7bc58fb57f2cd072ed13f7a22d1;
+ 30ce2f1fef6ef315
+ ""
+ ""
+ ""
+ ""
+ e071f4b5be472b5d27a62d3b59de4076;
+ d0798391805da08d
+ a3
+ ""
+ ""
+ ""
+ 9700bb529c726f7f9383103afde5c072;
+ aefc5f8584b7c5e6
+ ""
+ 17
+ ""
+ ""
+ beddb35cd6ce26eeccd01fc49467f581;
+ 669c0f16e39815d4
+ ""
+ ""
+ e9
+ 89
+ a6ea652052db22889858bba51b743f77;
+ cfce3ed1ecdf3d26
+ 4a7f16cb16c2e815f422cdf0c8e30308
+ be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a874498ad0abef8bc4fcb70e27e98
+ ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b009
+ c343474bde0f534fb167d4f0f45dc029376218f83a54b3dd22eaf08ceb381357ae3c3f73e48d26775bbb3d09ea1300c2
+ 9184a5120a75b987ebf1c111ee0f7fe0;
+ 51f284649016ed00
+ 456331854bc78bf43966eb0cfa9138
+ ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb82
+ 4173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc5
+ 8a5f8d241fd8edabb3447134fced691a560ffc16eb35351f299055d61c65a9d016a8a2aecd321e2aaba5be088bc4e787d23279d3b9
+ 2d94ce868ac29109422a40835e92df30;
+ 97f56ccbb2f294b38766fc69f6a9f2c094
+ ""
+ ""
+ ""
+ ""
+ cc3b89f1e518665f325656d16078b115;
+ 5ffd505003cc0cae9ce021a5f1fa4ffa91
+ 54
+ ""
+ ""
+ ""
+ 77f9efcf277f9618606fd47f5233bb79;
+ 4485f1a1258b2b9b8f0911e32d65cc1770
+ ""
+ a1
+ ""
+ ""
+ 4d91889c474511f47711a00d22a37021;
+ 8cbfe6effd1ff6778554acf1270485b203
+ ""
+ ""
+ a3
+ f2
+ db79e93136fbbcb2d167a14005e3e4f4;
+ c1c4c967c0a458cb948bdd409b687fa3a6
+ 827b480aa3a4c84cef64f6c9b53bf8f9
+ 57f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac
+ 8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397abfaf529ee41cf9a05c7efedef340153
+ 242f387588ee5c723abeac99f710a02c29c5d9420475d5c81cd7840cdb9c965b2357c9fd6cf4ed18247daf5e5b4908d6
+ 72aa25cd54aa0ed7bb78fdf9d491547e;
+ 9c51d2a90bbf7f1bfc338ab0ef5746ea8f
+ dcccd213e33f7e8a5718fd25014107
+ c8e7d715a92add9589d1f5c054b2d983514605ec590294a319b9802068a9f891bc5ba5afabf8c3122d12d7
+ ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7ab
+ 2ea09fe497954fcc5ff649f0c72b229294018f6d69846e4d55b35fcf561d6d73e36fd253241af102f1a5beabca9f878898bebc3c38
+ 018ad589b2a12c05238a52773fd66463;
+}
+
+serpent-gcm {
+ 60d7bcda163547d348b7551195
+ ""
+ ""
+ ""
+ ""
+ b7a5e3afee9d6b5d3272a42db95fe058;
+ e77022907dd1dff7dac5c9941d
+ 26
+ ""
+ ""
+ ""
+ 5a3f93b2c28c3208f3f470a28ded0981;
+ d0c6eb14ad568f86edd1dc9268
+ ""
+ ee
+ ""
+ ""
+ 31b6ec116273e033816b5ebeb8198b1c;
+ ee533285a6ed810c9b689daaa9
+ ""
+ ""
+ 06
+ 82
+ 1edf5ba454a8cd5ef0aac6153800a101;
+ 0d2d4b6003062365b0a54364c7
+ 6c160f11896c4794846ecfa14a7130c9
+ f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7
+ 080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61
+ 08276a3d1fd2638903bb85fd5ad5b3abf64d1e384ad5262501e198e697c210d778ef1ca2cb78e3fc462d18daaba7ee12
+ 75eb776d709e756036210b8d85056fdd;
+ cdbda3b3e9878731ebfedd4705
+ e505da1435dceaa7b1cc49ae
+ 1d50c38201a894476b3f102b752eb952953396
+ 6f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33
+ 6cf5fafa1f1b67aef17c51ecd4cc8807863bb47816d9416eee45e144973c6bfe325b1dd7b29af06a4d9b0e2f993127dcbf33e8075f35781fe7
+ 8827e78f2a8ba21a12f6c4078713d83b;
+ d090c54215abd6b3ad54efc9a3
+ 8378c5b93bf4f2aad2605faee2b03f
+ b648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee
+ 72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b04
+ 11687e1abefb35846b4c37d820220610a076a589e33bdc58b8b9f4f5318a945421139b3122e26578e3d34e00ab2cb88a0de1590b46
+ 75d611a4d23fc1cc399cb1d06475c400;
+ 67cb9fc2712a199e533fa915
+ ""
+ ""
+ ""
+ ""
+ 2e79ef91df0515538a3bf641867668d4;
+ 6308cdec3f768281e040a9b9
+ a2
+ ""
+ ""
+ ""
+ 4a3d8a26dac3498e97ec445243d6073f;
+ 22bd689aef66f5306ceb0c6b
+ ""
+ 08
+ ""
+ ""
+ c47eae4dc6e8e34fd594bcf425c93137;
+ ac8b0a22260c571b4a42bb8f
+ ""
+ ""
+ db
+ 08
+ d328c14d09ea87f05101640b5c19ec06;
+ 233bfa6a5cfb0bad7d95214a
+ de49cb3b6f5fe8368131115c037ba323
+ fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6
+ eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f08345
+ 681e86e5aebd4a9648b78daa6bc86d34de3970fa7065f26789d65cb8d0d05639849b612fef76214315948d44f3e9c512
+ 2a4f1ff8cc104ded9d693f28d62396a3;
+ 5b663e4ee1315f3c8f2aebfa
+ 921451dcd1af5813b70d30ce
+ 2f1fef6ef315d0798391805da08da3aefc5f85
+ 84b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684
+ cbd8037fa6cca0d3c5d760f9775d6ec6b3349a80089425f3a72f47fa138d41ddb7d165fdf2df4d5ea97d430b173363a87cf9d61ef829127ba7
+ f2f7d0abeac736dbcb17c8b11a614ef5;
+ b5aefa69a4cd52147ed12ca9
+ 86981a874498ad0abef8bc4fcb70e2
+ 7e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720ee
+ f9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d8
+ 78aad8dbb0a294e0d23f61421d9adf39e537651cf5d91bc9e815307a021e916467f1abae1cf7eb09aadf42f053f6c9dbb099b7587c
+ f40974b1334cf4c25e29bc26f608bf94;
+ 58cbbc8424d126b8
+ ""
+ ""
+ ""
+ ""
+ 65a882a10602424ef433579558fd91db;
+ 07e6daa089c3f909
+ 9c
+ ""
+ ""
+ ""
+ 67a19a1d408be278d46cb09c2d09e5ca;
+ 5ffb824173d7634c
+ ""
+ 04
+ ""
+ ""
+ af4590dab6b84c9ab769597a6075bb40;
+ 226f30cbb7f0e4a9
+ ""
+ ""
+ 73
+ 19
+ ee176a9eb69f35199805f8c19b5061bb;
+ a8cd190107314717
+ a77456f3ff669c732b58db8f48af65f7
+ cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4ffa91
+ 544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967c0a458cb948bdd
+ bcece9311f7669d6f744b547aafeba06c7cb05e623325f183ec1c0b24424f612b10a539f684fd1c0730ee75e5deb2b55
+ d6c09aed972bfb56ab024c80fa114965;
+ 409b687fa3a6827b
+ 480aa3a4c84cef64f6c9b53b
+ f8f957f4b03cf43e89957f9a3e8128f8743d16
+ 687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2eccc
+ fd90ce8763bd7ad21f288077677eb3cfee48137ffe89d5c5965b3d99592896c4eb94b6573c1610d266609da17e3192a833bddc1a656e91b4f0
+ 87a7ea3dc29335c676a2d8453d5232ec;
+ b44d65bad397abfa
+ f529ee41cf9a05c7efedef3401539c
+ 51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a5718fd25014107c8e7d715a92add9589d1f5c0
+ 54b2d983514605ec590294a319b9802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe
+ d29ece81f1d8523540fd3e4edae0f717730b301f05f3c9fae128581349a2740ae49266ed8d83a2216072ed232e280163b9531f80c1
+ 9f123aa15e25f65aeda0a8c05855c696;
+ 079753ee1a957eb6d6699e6b7ea2725cb2
+ ""
+ ""
+ ""
+ ""
+ 0d19fefb39f9d5ca47305f578da4c2a6;
+ dac07ecde95759ac46fee6dda7abc8ad68
+ da
+ ""
+ ""
+ ""
+ 33e9c876994b5d473cee7028bd8bc422;
+ ac90cfe22d2f1f2968cc42fa8b669ed3bb
+ ""
+ 35
+ ""
+ ""
+ b5f2eefdbd65dad3c85637c4644d81b8;
+ 42a9cf44bbc8c6254d980398bd94e66eb4
+ ""
+ ""
+ 56
+ a1
+ 41f9c05ae9ec028487faba6297d754aa;
+ 3d405e51881e99027b8ab9aea3ccf860b0
+ 009740763d96836c5f87b95460938de1
+ 288c69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c3680
+ 0d9645563a308ba60076817523bd2abf1261b089d8f23a9c2835076a23faac2cdd67771cc667a8331f0a170b66283e4f
+ 62a4e874b9bed58dfa604492bb7d314c941a359fb4704211a03bb5efb5bd1ead5f4bc209c9ed2ec55945e542da07de30
+ 9ab10e04cce4cdb21816a452838e207e;
+ 834a06148f302c3973accd56f6f24e3395
+ 8b8c2e2352fd61e4fa8fec81
+ 6ac861a8b33779f09e7a10fc02a8f48afa3080
+ ee119a52a9a817e4f2b94b0820cab383a8cffeea7c486315799dc875fba578c8ec4837898a92142b5b0677da1ac273117b45bcfff5d5f8b6fd
+ 6be1ebdac5a498d5c1005189710616d5317726377ccdde02d771a44d9127704c821f1056a1079d34e742ebfdfd11ef3aea46b18655bb2ffe88
+ fd98fa8d62a384d07a991fb3caea3398;
+ e2893232a9f81d14517ffae475f6b94a43
+ a67b3d380d2f9aaafe2dd721c0095c
+ 8808847689211450ba8095ffab1eaadf66fd22ac1976063e113ab61f813e28a1397a7974a1d7f4220c785f
+ e426a5a0e80f678d404147842941feeffdc2eb44dc8c0d5e8f444f7f4e0c893959b74dc23a7bb40e7e0013e5150686d2301b43a15a
+ 100ee38a4070af0c2e7ea43836fcfa78a65278a09ab122bdcdba11d93b63c2965341b19ff4be55ced558fa76d5c3fcb0227e037572
+ cec6a5923cedad5ad0bc6551a039ed2d;
+}
+
+serpent-ocb1 {
+ 60d7bcda163547d348b7551195
+ e77022907dd1dff7dac5c9941d26d0c6
+ ""
+ ""
+ ""
+ 686b0aac51a25d6f2878b1e50e2badbe;
+ eb14ad568f86edd1dc9268eeee
+ 533285a6ed810c9b689daaa9060d2d4b
+ 60
+ ""
+ ""
+ 2811539055c7b5c0e10cabfd66d63d09;
+ 03062365b0a54364c76c160f11
+ 896c4794846ecfa14a7130c9f1371206
+ ""
+ 34
+ b7
+ 736d9cb5d0427f0eea7a387136323745;
+ c9519848a877ff77bf79192a5b
+ 50ade5d9cd739a3d1f337f29549e6b0d
+ ""
+ 27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e
+ c3b13eaa510c580acba8cba253b30f944b369f12002ddefee96ff13f3e7daa0e9836f355b08a055f75839883f3ae65a3
+ 81f7d94ad9ffd90dbfaef2d3643f1470;
+ 6057acc87638f508046733d9ff
+ 61cdbda3b3e9878731ebfedd4705e505
+ da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5f
+ a450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54
+ 6f6ee0f2bfb91b2eaafde0609efb27f9df091d396cc5932c67c3989439a21fd0528a27da02e746de3bd96e6692f8bfc8
+ 05aeefe7a4a38c082ec19f1ab2404541;
+ efc9a38378c5b93bf4f2aad260
+ 5faee2b03fb648e27fff63102758fe2b
+ ""
+ 69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9e
+ 2fa135d2df5aa9ed43e094bba67d692edefd217d7d8f2c64a0f8a2c728176ddd7e699e8ff6681e2508ab05b1014bf461fc21d13f14
+ ba576b55bfc099c9cf4db5c28e90b761;
+ b53b571ea629c54d57dd2d42f7
+ 0800df9fcbaca48b77dba189196d1ebb
+ a10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b
+ 0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da67
+ ee27f377eff38f2464b289b25dee0a73b9a803fbf821ec328a488dce759e240625a7b3103d49c590858da2771988d0c66c21f12884
+ 54ef913069c3dd1c9685f2472b7fc3f4;
+ 94c18b5337685a96ed65b9ac
+ a338527ef19b09c063c46f88de9fd41e
+ ""
+ ""
+ ""
+ c4b88fee21ecbc1ffbf6ea083a080716;
+ 72d7b97e23e6eabdff3bcd21
+ 1499268878dbf30f1dad89d4b9b12012
+ e4
+ ""
+ ""
+ 8e5107d4d70c8a727e44b79fbce267ef;
+ 713df46795630e7952d22bb0
+ 2d7100b8b649377d20a8f083455b663e
+ ""
+ 4e
+ f2
+ fade84801d77de290eb960862c98d943;
+ e1315f3c8f2aebfa921451dc
+ d1af5813b70d30ce2f1fef6ef315d079
+ ""
+ 8391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e303
+ 48a4a77a5651db3c1dd8baae2ce157c1411d1e70c22826da41446890d00ef14467c0439f1f0d10ed95ab8ee0f624f64c
+ d2c05303138ae9ec11f3320c4a9fc1fa;
+ 08be3c31e6bc58c0b7cadcb6
+ 58b970e47479a684b5aefa69a4cd5214
+ 7ed12ca986981a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9
+ f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908
+ 402444f7ccf9e0aa13173b33afe0bb1e38c233ade7ff56f92a24bd8d17cb137ad49475b39cf3c34a56d074faa7449405
+ 67924f31b67c3fc19ed79b5df55e286a;
+ 445608fe95e81c2533e31c9c
+ 1a9851bc2810d858cbbc8424d126b807
+ ""
+ e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3f
+ 5fee9263e96affb3166ef4f393ad28c9baac39c0bcd021025d930e9c4ae105ed386f4664d28857b8d29c83f377590385c8252bbbac
+ 3ec53f10d421ae13299f734e4c33c5c4;
+ b90e1721b730374ffc9bc597
+ f56ccbb2f294b38766fc69f6a9f2c094
+ 5ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff6
+ 778554acf1270485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f
+ 613d48844e3ff8fd0fa43fe6356b519c8e851d8b70f90d4bbb82905ac14e77e4ce53fb727b8c408bda29425856f06d722308628b27
+ 2e3f1daa8e87557852dbb4d5a9f0e978;
+ 9a3e8128f8743d16
+ 687b7bb8deb9bd205b70e04c091d205c
+ ""
+ ""
+ ""
+ 595360839f7632d4470fad88b88bcb17;
+ dad9e9a79b1abf91
+ b0851e5ca605ac845139958701167750
+ 8a
+ ""
+ ""
+ 446bce84dfdd94177e90e9bae6bfc1c5;
+ 15dde524af3e2bee
+ 0646541a42c2ecccb44d65bad397abfa
+ ""
+ f5
+ d6
+ 1c8be9521e25a947fb8bcea3f3e095cb;
+ 29ee41cf9a05c7ef
+ edef3401539c51d2a90bbf7f1bfc338a
+ ""
+ b0ef5746ea8fdcccd213e33f7e8a5718fd25014107c8e7d715a92add9589d1f5c054b2d983514605ec590294a319b980
+ 3f68fd5d2677fb15a8c99b65baf1e8aedb5a71b8756fd5326567128473762ae4498809325d9f2d1a031e58b9f181266f
+ 723cde60d1e536a1e076650f3261f473;
+ 2068a9f891bc5ba5
+ afabf8c3122d12d7ff3c41122d70d17d
+ 4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68
+ daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4563d405e51881e99027b8ab9
+ 9f5e2d1dd5454687873145ef6970fe06636195562fabbad9a3a76bf0dce03732a32ed87a326e3e8e9b1c5d0f41bcda54
+ 802ccadfb7baaf0b6cf6579eca51f720;
+ aea3ccf860b00097
+ 40763d96836c5f87b95460938de1288c
+ ""
+ 69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c36800d9645563a308b
+ fb81a3b2a097da78f981bbb53b2623f6271fd097fb6d126851ff942038904f0fb2cf4e265448c30df6a94559ae260d00a81af76545
+ d9290c98d01f6032bf110b61657e165d;
+ a60076817523bd2a
+ bf1261b089d8f23a9c2835076a23faac
+ 2cdd67771cc667a8331f0a170b66283e4f834a06148f302c3973accd56f6f24e33958b8c2e2352fd61e4fa
+ 8fec816ac861a8b33779f09e7a10fc02a8f48afa3080ee119a52a9a817e4f2b94b0820cab383a8cffeea7c486315799dc875fba578
+ cee153d3db504d8bb1d7050124952705e0eb9150cd5806e0b40f104eb15167512699f11b129604f7f36915159f592171dbb89b5604
+ 5c96b8868aafbcb195e23f9335d73535;
+ c8ec4837898a92142b5b0677da1ac27311
+ 7b45bcfff5d5f8b6fde2893232a9f81d
+ ""
+ ""
+ ""
+ b71d7a6b4f83e6276400173ddaeb0be8;
+ 14517ffae475f6b94a43a67b3d380d2f9a
+ aafe2dd721c0095c8808847689211450
+ ba
+ ""
+ ""
+ 7c5df02df2e106fed4414626ae5b5315;
+ 8095ffab1eaadf66fd22ac1976063e113a
+ b61f813e28a1397a7974a1d7f4220c78
+ ""
+ 5f
+ 86
+ 6a7d0527c06c781aea0a6b0389048b08;
+ e426a5a0e80f678d404147842941feeffd
+ c2eb44dc8c0d5e8f444f7f4e0c893959
+ ""
+ b74dc23a7bb40e7e0013e5150686d2301b43a15a84e81d7f5cedaa49e2414ebf47970e560475cff206877de69146acc3
+ b6c017318dda6d2389ab13ae89849c2944a151d982f0490074e38594c6f6a819c3ed133cca4493d84434228645dd47f7
+ 6eebac1b2230b2fca6daefff666d4cd3;
+ ab6cf8556b7aa776945948d1b8834df219
+ 6c92ec1718dcdeee0d52d9539726d281
+ 0391b3f9d10c39b07ae8f08ce7cee4758a386a9943e97dedfbe61e737882cd09c2b9a80f34c0fde11c2481b11fc76bfa
+ 4dbf710a9e544e0c536ca1e040f9ad5b04140d98edabe08485290a4d87d13b07398a1458c2c6b61dbdbc1cccada8c1a0
+ b1493269b6bc9b0c2a95e3b26c0df50fd48c5505c85d0f1cc545cb8ee4b9aa1917e71d2f8628a3b38d6282fa23d4021d
+ a6fe44618a21904fb885560b2dca9e2f;
+ a9aabb6c4e3c3554f8fb1ef61614c27029
+ 5dfc0ca6551ca4bdb75359f91cb9d921
+ ""
+ 056b7de74fc9a9b37154ce6c0b396179d31f06a1dd5982cbc0d7cb23841da1ae8f4ae480cda98ad6cf2bacf6f9fd3f821330c43f3d
+ 5ad848d7910c43775ad95850550e36ed4f51a9180a1558752ef9043d53d15b7328f82cf31dd6e89fde07890019b7cba632600d6c87
+ 58f508482940235912a6955d16d75ac4;
+ f6c2b3fac7cbcf96523d4723f91801325e
+ b8553236651c96788d73d192ee53b3f3
+ ebd66ddd98cedbe88e245de25b1593b70f8601562d90a9b59ed034a867642d25d54756fa5c47f16f64b837
+ bb4926214211a1c696ba172010abb433922a22d9fd881519165eb9d85197a21cc34ac0d5ae7be8dbf98e4ffed2cf6b1372a5aa47b5
+ 8450286f64f58e3f5cd1d62c28db59591ddf05384d3eaf824acdd8febc6f56595d91eb32d608beabe8f31117a5b42e8d38863be19d
+ cd0ddc15fdb0b43ab9c1da27dab961e9;
+}
+
+serpent-pmac1 {
+ 60d7bcda163547d348b7551195
+ ""
+ 86802543a1d8ca8f65b1bb3e0d31d221;
+ e77022907dd1dff7dac5c9941d
+ 26
+ dbe75897dbb97ea7a0545fe684170ede;
+ d0c6eb14ad568f86edd1dc9268
+ eeee533285a6ed810c9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f1371206
+ 13c3430e93df53d7da7833282eee3c25;
+ 34c9519848a877ff77bf79192a
+ 5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd8
+ 3af04cadceba44ec5a6897e499e82f51;
+ 8374d8cde8e160ad10997a21
+ ""
+ 1d72b61bfec2412d29f3f0ecad5d04c8;
+ 635c6d62c9269029df3e6057
+ ac
+ 3441e6813346f41a8f780f9921ccf0ea;
+ c87638f508046733d9ff61cd
+ bda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb6
+ 297ec48558af83ac8ebcb3e442fcfc8d;
+ 21b7f65b000961040ef2f9b2
+ fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c5
+ 1c6db42246e98e9eaa43a287e5c7161c;
+ 4215abd6b3ad54ef
+ ""
+ e79dc50690f53356f567c3fe1845e31f;
+ c9a38378c5b93bf4
+ f2
+ 01c74df5d34de8442b6e0dea2f43cfcd;
+ aad2605faee2b03f
+ b648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219
+ e36a0ed637bc357b41d7ca57834fe1cd;
+ bfb474fd71d891f2
+ 4bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9f
+ 1f2abc9e954b1e7d282ef8c3ee00fea4;
+ c2712a199e533fa9156308cdec3f768281
+ ""
+ b498a64086f85b98d362950e079b3624;
+ e040a9b9a222bd689aef66f5306ceb0c6b
+ 08
+ febb2df39da1126d67fa08e337c430d1;
+ ac8b0a22260c571b4a42bb8fdb233bfa6a
+ 5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65
+ 7f8f5f88f99a29146523eec2910448f5;
+ b9aca338527ef19b09c063c46f88de9fd4
+ 1e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d
+ 0c21a0dd3a264c1ef7cfeebd6aa8c2c8;
+}
+
+serpent-ocb3 {
+ 60d7bcda163547d348b7551195
+ e77022907dd1dff7dac5c9941d26
+ ""
+ ""
+ ""
+ 4f7cf8f6ab514ac1f3727f957c772859;
+ d0c6eb14ad568f86edd1dc9268
+ eeee533285a6ed810c9b689daaa9
+ 06
+ ""
+ ""
+ 49cd7a3bc7a32c2f5ef6c4097d9f3e48;
+ 0d2d4b6003062365b0a54364c7
+ 6c160f11896c4794846ecfa14a71
+ ""
+ 30
+ 22
+ 1105ad05b7e04476b4c7a746a45538eb;
+ c9f137120634c9519848a877ff
+ 77bf79192a5b50ade5d9cd
+ ""
+ 739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a
+ db5d464d5b9a3659805cb7a3e720721f7b6963be1c93ca3d5ad39b5bfb7d12aaedab640a6d098a0561198d05cd9fda2d
+ 25430830a120e8e713128afa579ce1cc;
+ 21635c6d62c9269029df3e6057
+ acc87638f508046733d9ff61cd
+ bda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb6
+ 21b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a480
+ 402dce04d49efb3aff4154a91ab4117d865b8c1e894e3e0170dbf421ca1a92addbe8599f92ffccaf4a96bf1ea5fe54ee
+ 00589c1be04b5aff3a9eba045c305801;
+ 30370c33d090c54215abd6b3ad
+ 54efc9a38378c5b93bf4f2aad260
+ ""
+ 5faee2b03fb648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219
+ 48023bca0cfcdab03c28493ddbe3146a43b44d5037d87ca0c870c2c0fabb60896dfb1298de927f195884f29edd914e3e2097071103
+ 6979cd907d468b65143ea75140e38ebd;
+ bfb474fd71d891f24bb65d1563
+ 259f9eb53b571ea629c54d57dd2d
+ 42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040
+ a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c
+ 559ea712ed9f509cf3ac9d44f1ac8cd0c6a11fd7e5250ce0de79f197f51f82903e8da278b4c5dbf8bcbebe7f52446cf523bee00462
+ f15cb4b18193f4922298801f9323a3c7;
+ 037ba323fe1dc8151784873f
+ 0eb5b647da6794c18b5337685a96
+ ""
+ ""
+ ""
+ b7dd404d4f1a01c8ef737b6c2525a3c1;
+ ed65b9aca338527ef19b09c0
+ 63c46f88de9fd41e72d7b97e23e6
+ ea
+ ""
+ ""
+ ab6815775c61984db8e9f4927af022a0;
+ bdff3bcd211499268878dbf3
+ 0f1dad89d4b9b12012e4713df467
+ ""
+ 95
+ 7b
+ 70aa0ae770a0161e22bc0ae606c70527;
+ 630e7952d22bb02d7100b8b6
+ 49377d20a8f083455b663e
+ ""
+ 4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f
+ 5ae21390a16833b1553ad00340cf88608eef0c77dec11bf992c8371c330f3c3b76484c95384949ec2cc42d1b943665f4
+ e0bd36e53a42d1c06bc4ef6ac241d106;
+ 16e39815d4e9cfce3ed1ecdf
+ 3d264a7f16cb16c2e815f422cd
+ f0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a874498ad0abef8bc4f
+ cb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb
+ a5b3449e8af9f06e72f5f618131e205714de08712af78c71173e347e29259efd49ef786eebfb7fe5592e2838ca92f9f9
+ b6491d77b553f97cc3684ef4e7339515;
+ 1c8dd0b00951f284649016ed
+ 00456331854bc78bf43966eb0cfa
+ ""
+ 9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f
+ 0eb3df5285a44b93df6263d4a19c3468cc98d13cc57c92671fe450936feedb2d692d6e9b288ca7095ba3a16fc553d2b33f2e5e3285
+ ed1441556cce090353a8e651db8b7765;
+ 30cbb7f0e4a973a8cd190107
+ 314717a77456f3ff669c732b58db
+ 8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0c
+ ae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967c0a4
+ 72c70c50bfc9891abb5d0f389a48e4ba925f1a5de1b522dfec32d0de805500ef56a0e3b248e52d50461e8673b51591d76aa7aac188
+ 22315e09ed36b5e886972e3d97bb191f;
+ 58cb948bdd409b68
+ 7fa3a6827b480aa3a4c84cef64f6
+ ""
+ ""
+ ""
+ 30c1077f4bdf19d1a75c2bdb0b791be0;
+ c9b53bf8f957f4b0
+ 3cf43e89957f9a3e8128f8743d16
+ 68
+ ""
+ ""
+ 6f663abf27387105cc24b69ac2377f89;
+ 7b7bb8deb9bd205b
+ 70e04c091d205cdad9e9a79b1abf
+ ""
+ 91
+ 74
+ 81956eab259749fa15c9a0c287a3c797;
+ b0851e5ca605ac84
+ 51399587011677508a15dd
+ ""
+ e524af3e2bee0646541a42c2ecccb44d65bad397abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf7f1bfc338ab0
+ c229d22e2e97fdec03bf8725e466fe3130ef56c17c910ea6f6023fc4f389deb33eea058fd7878ee3f0947107da6ee92d
+ 5bea96a8d2416fbb9f616e27b8d67b62;
+ ef5746ea8fdcccd2
+ 13e33f7e8a5718fd25014107c8
+ e7d715a92add9589d1f5c054b2d983514605ec590294a319b9802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70
+ d17d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8
+ 67125d08b30abdf348054dd642f18f0802d58b7ad3f49abd77ee6e68146696f42a4a73993f0d3fd2754033dfafcf0b49
+ 51db397a26bccb5dfb66aa47d15dc1ed;
+ ad68daac90cfe22d
+ 2f1f2968cc42fa8b669ed3bb3542
+ ""
+ a9cf44bbc8c6254d980398bd94e66eb4563d405e51881e99027b8ab9aea3ccf860b0009740763d96836c5f87b95460938de1288c69
+ e20ad6334c2ecfaf8546c5917542e2b65b534724eefad63e1061805e673a6358d31753bdd4beb457112d41ccb39c306ae4aceb1fea
+ bb503bc1e42a7c837197827d4c4ba6ac;
+ d80ea12ff4bb5f06
+ 9b8a2e86041c1b9fc214e9ca2186
+ ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c36800d9645563a308ba60076817523bd2abf1261b089
+ d8f23a9c2835076a23faac2cdd67771cc667a8331f0a170b66283e4f834a06148f302c3973accd56f6f24e33958b8c2e2352fd61e4
+ 13d0dff205001c5b6bf86c8810569bf634631c25dc146faf019d31b13437331abd317718f12e056d365c8d36520746656efd5fa8b1
+ a281566357e03991bc302355006a4df0;
+ fa8fec816ac861a8b33779f09e7a10fc02
+ a8f48afa3080ee119a52a9a817e4
+ ""
+ ""
+ ""
+ 62e171992b3e9b84abd46d11865c70fd;
+ f2b94b0820cab383a8cffeea7c48631579
+ 9dc875fba578c8ec4837898a9214
+ 2b
+ ""
+ ""
+ c00cc0b5bacedb125f578b30d84d2198;
+ 5b0677da1ac273117b45bcfff5d5f8b6fd
+ e2893232a9f81d14517ffae475f6
+ ""
+ b9
+ 78
+ 8a8a1da60db0bbd76cc5c4bcac79da2a;
+ 4a43a67b3d380d2f9aaafe2dd721c0095c
+ 8808847689211450ba8095
+ ""
+ ffab1eaadf66fd22ac1976063e113ab61f813e28a1397a7974a1d7f4220c785fe426a5a0e80f678d404147842941feef
+ 7a160e50b050bb3ca62c12501226cb0551b4dc3349721d71e08ccf2222dd831ac2a108691039f1ba41fc326d2a827bff
+ da9c04168e6dedb3579c2a9bd76f1692;
+ fdc2eb44dc8c0d5e8f444f7f4e0c893959
+ b74dc23a7bb40e7e0013e51506
+ 86d2301b43a15a84e81d7f5cedaa49e2414ebf47970e560475cff206877de69146acc3ab6cf8556b7aa776945948d1b8
+ 834df2196c92ec1718dcdeee0d52d9539726d2810391b3f9d10c39b07ae8f08ce7cee4758a386a9943e97dedfbe61e73
+ 7e0bd98a04cf07134ff5026bf10c6e2a4fcaead969223f4729ff57cc2d72f9c6976a03e4932fda63cacab98244f36385
+ 34b97cb4b3ec851d86540afaefb7e6e5;
+ 7882cd09c2b9a80f34c0fde11c2481b11f
+ c76bfa4dbf710a9e544e0c536ca1
+ ""
+ e040f9ad5b04140d98edabe08485290a4d87d13b07398a1458c2c6b61dbdbc1cccada8c1a0a9aabb6c4e3c3554f8fb1ef61614c270
+ 58c88119379227a3438f4be71c2b148eaae5dc87f047a10ac315de213b318eb0fd13be48c01b39654ec0521caa1da513b9fc1b9947
+ 1176c87b5d31fb87b7454e7aff5104ba;
+ 295dfc0ca6551ca4bdb75359f91cb9d921
+ 056b7de74fc9a9b37154ce6c0b39
+ 6179d31f06a1dd5982cbc0d7cb23841da1ae8f4ae480cda98ad6cf2bacf6f9fd3f821330c43f3df6c2b3fa
+ c7cbcf96523d4723f91801325eb8553236651c96788d73d192ee53b3f3ebd66ddd98cedbe88e245de25b1593b70f8601562d90a9b5
+ d5559d4ffc3be85cfdb261126b89cb7e7fae82a3f954bf79ffe6f7603ee58b5d2d37747ecfa24ad41bdaa0b1fd7c82e0e04e81c69f
+ 507ed27681b30a6cdaab64aba8bb3ac1;
+}
+
+serpent-ocb3-mct {
+ 16 36d3bf694fedee5e20e35745d9f647e9;
+ 24 924c5b38d6df87dab11042e56bb0434e;
+ 32 5b8e3684bde5c8b28bb87796aaf95b17;
+ 16 506bd45f5b6eb67ceeb408b9;
+ 24 650f258975a5d1f6596ff2af;
+ 32 fd5488e927ecafd96722e92b;
+ 16 5294561007b55710;
+ 24 d3a5062ec84f5ac8;
+ 32 2b883de71615444d;
+}
+
+serpent-ocb3-mct {
+ 32 5b8e3684bde5c8b28bb87796aaf95b17;
+ 28 1a93fd62a9e9a3cef4407833bcaba842;
+ 24 924c5b38d6df87dab11042e56bb0434e;
+ 20 626a7bdd05dfbed8287c7a7cec11b863;
+ 16 36d3bf694fedee5e20e35745d9f647e9;
+ 12 5a6486f6ba3b10d486c628147c71a85c;
+ 10 0664a0cdd817da522ce92837ec06ebc0;
+ 8 aa155e08b41857c4abe54180e6c50bbb;
+ 4 328cd59c0a989fb70c0339066da49aa7;
+ 32 fd5488e927ecafd96722e92b;
+ 28 f080658ee65dfd9d54e19ae5;
+ 24 650f258975a5d1f6596ff2af;
+ 20 d141c903a4d29332b36b2984;
+ 16 506bd45f5b6eb67ceeb408b9;
+ 12 3c53bf904f4edbb691e7af8e;
+ 10 849f7d73dd7e48655f062340;
+ 8 048b157a38f4281968f840e7;
+ 4 f52c2156342549de8bf99f08;
+ 32 2b883de71615444d;
+ 28 d9776aee81a378ea;
+ 24 d3a5062ec84f5ac8;
+ 20 e1e805b319485007;
+ 16 5294561007b55710;
+ 12 00edada26968f413;
+ 10 dff51ca249d51583;
+ 8 87ec3336240f6f98;
+ 4 305dce068342b3ca;
+}
06e3c0e541f4aae6fe93 40009f8a465a9feb 0e7aace421bc79d8;
2ea09f1cc89e064f09bc 543208b05bfa3858 a95d87fad12c3593;
}
+
+skipjack-cmac {
+ e4bef260d7bcda163547
+ ""
+ 5a0fba9745b5a83e;
+ d348b7551195e7702290
+ 7d
+ 8610508eeee08d29;
+ d1dff7dac5c9941d26d0
+ c6eb14ad568f86edd1dc9268eeee533285a6ed810c9b689d
+ 46b1504483d84dff;
+ aaa9060d2d4b60030623
+ 65b0a54364c76c160f11896c4794846ecfa14a
+ cffcc55881902725;
+}
+
+skipjack-ccm {
+ e4bef260d7bcda163547
+ d348b7
+ ""
+ ""
+ ""
+ a8e3e588;
+ 551195e77022907dd1df
+ f7dac5
+ c9
+ ""
+ ""
+ 3b47dc26;
+ 941d26d0c6eb14ad568f
+ 86edd1
+ ""
+ dc
+ fe
+ 61bfe011;
+ 9268eeee533285a6ed81
+ 0c9b689daa
+ a9060d2d4b6003062365b0a54364c76c160f11896c479484
+ 6ecfa14a7130c9f137120634c9519848a877ff77bf79192a
+ 3599e35441a20dab5e973151a0f3d8dbde983d9a896d3463
+ dee97ef167dde431;
+ 5b50ade5d9cd739a3d1f
+ 337f29549e
+ 6b0d27a4ba234085406a6136512061f7080cc0
+ 7df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029
+ a72ba97fe436bdad5e7416aa41b733be94324faf2d70cc67a31559f7d7
+ d14f0eba040f800d;
+}
+
+skipjack-eax {
+ e4bef260d7bcda163547
+ ""
+ ""
+ ""
+ ""
+ b15f1791e4065ebd;
+ d348b7551195e7702290
+ 7d
+ ""
+ ""
+ ""
+ 58aed98d9796d86e;
+ d1dff7dac5c9941d26d0
+ ""
+ c6
+ ""
+ ""
+ ed16d102bdd549c9;
+ eb14ad568f86edd1dc92
+ ""
+ ""
+ 68
+ 1c
+ c1a5644ab08ad1dc;
+ eeee533285a6ed810c9b
+ 689daaa9060d2d4b
+ 6003062365b0a54364c76c160f11896c4794846ecfa14a71
+ 30c9f137120634c9519848a877ff77bf79192a5b50ade5d9
+ b4bb56af916bc1a14e6a106346b9fbc1989b20d12275469f
+ 06a4958aa50a4260;
+ cd739a3d1f337f29549e
+ 6b0d27a4ba2340
+ 85406a6136512061f7080cc07df0591d8fa21f
+ 2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc876
+ 1e9afd31797d761c4f9ffbf0031a227872fa8b21de658b8fdb22514c48
+ 44adbb6a2eae0a93;
+}
+
+skipjack-gcm {
+ e4bef260d7bcda163547
+ ""
+ ""
+ ""
+ ""
+ 6fa498e64c57905e;
+ d348b7551195e7702290
+ 7d
+ ""
+ ""
+ ""
+ cc2fd0c06756c545;
+ d1dff7dac5c9941d26d0
+ ""
+ c6
+ ""
+ ""
+ d6c1997db60c0a1c;
+ eb14ad568f86edd1dc92
+ ""
+ ""
+ 68
+ 98
+ 08825f061a3ea120;
+ eeee533285a6ed810c9b
+ 689daaa9060d2d4b
+ 6003062365b0a54364c76c160f11896c4794846ecfa14a71
+ 30c9f137120634c9519848a877ff77bf79192a5b50ade5d9
+ 0a048d8b451ed2cd53dc70a177834525881e84046c4dd904
+ 222801fac5bfd46c;
+ cd739a3d1f337f29549e
+ 6b0d27a4
+ ba234085406a6136512061
+ f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029
+ f3bf97b9c9c15761437a42c826abadf01e9207fd4b172e200a6d7aea3a77c85c3a
+ fff6db552209b7b8;
+ df3e6057acc87638f508
+ 046733d9ff61cd
+ bda3b3e9878731ebfedd4705e505da1435dcea
+ a7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb6
+ b96e1e6d2db5000c5bbbd06e86ab26c3a2a060b3eeeb1899793a743bc9
+ 74694b07f5866d80;
+}
+
+skipjack-ocb1 {
+ e4bef260d7bcda163547
+ d348b7551195e770
+ ""
+ ""
+ ""
+ 28afba7b57208bb2;
+ 22907dd1dff7dac5c994
+ 1d26d0c6eb14ad56
+ 8f
+ ""
+ ""
+ 62f000b7bdb0d1dc;
+ 86edd1dc9268eeee5332
+ 85a6ed810c9b689d
+ ""
+ aa
+ 84
+ c92bec4a841eab50;
+ a9060d2d4b6003062365
+ b0a54364c76c160f
+ ""
+ 11896c4794846ecfa14a7130c9f137120634c9519848a877
+ 50d328a84a166d75e1574aafc3a6847451f766a4e5b1d506
+ c155363b2c86bd70;
+ ff77bf79192a5b50ade5
+ d9cd739a3d1f337f
+ 29549e6b0d27a4ba234085406a6136512061f7080cc07df0
+ 591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9
+ b9f8bca7a0f1024a232217f4d9acd0187997bdb2348287f9
+ d8d3f45231b59769;
+ 269029df3e6057acc876
+ 38f508046733d9ff
+ ""
+ 61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c3
+ 3b5a6606907f297d26827ab95798171debff551df36e0ae8f6f29026f8
+ 24734c1d6c3da996;
+ 8201a894476b3f102b75
+ 2eb9529533966f27
+ 043eb621b7f65b000961040ef2f9b2fc5fa450
+ 727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a
+ 694a1412b0ab1b6fb698a9eb920fd2910c7625b68558fbe9ffda426f55
+ 19c658ead145b558;
+}
+
+skipjack-pmac1 {
+ e4bef260d7bcda163547
+ ""
+ b663da5674ffc5d1;
+ d348b7551195e7702290
+ 7d
+ 554a2fb9de2d30ae;
+ d1dff7dac5c9941d26d0
+ c6eb14ad568f86edd1dc9268eeee533285a6ed810c9b689d
+ 0318df96a103a2f1;
+ aaa9060d2d4b60030623
+ 65b0a54364c76c160f11896c4794846ecfa14a
+ b3a737b39bf1c95d;
+}
+
+skipjack-ocb3 {
+ e4bef260d7bcda163547
+ d348b7551195
+ ""
+ ""
+ ""
+ 306c2123c229d86a;
+ e77022907dd1dff7dac5
+ c9941d26d0c6
+ eb
+ ""
+ ""
+ a0f5e0a9d6193d8e;
+ 14ad568f86edd1dc9268
+ eeee533285a6
+ ""
+ ed
+ 76
+ b1f29902bbde9441;
+ 810c9b689daaa9060d2d
+ 4b6003
+ ""
+ 062365b0a54364c76c160f11896c4794846ecfa14a7130c9
+ 62299168f2ce7ea1488f71fbde61613002efcc4815d4674b
+ f9d14a84093df62a;
+ f137120634c9519848a8
+ 77ff77bf79
+ 192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba2340
+ 85406a6136512061f7080cc07df0591d8fa21f2dd88374d8
+ 7ee7aa9e2d4e7e5f4b9c9e254ffd3868f8ce577bc82b0239
+ 0560b1fcaba5682f;
+ cde8e160ad10997a2163
+ 5c6d62c92690
+ ""
+ 29df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd47
+ 914f81636ba12b551c60b41dcf566e447d02d15d2113c09678b1fca4ae
+ b7161acf1efb88ec;
+ 05e505da1435dceaa7b1
+ cc49ae1d50c3
+ 8201a894476b3f102b752eb9529533966f2704
+ 3eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d
+ 78498440ea075861116531b9ad62fa7d399948260edc0bdd04e04a4327
+ 39de18c8572cfd02;
+}
+
+skipjack-ocb3-mct {
+ 10 63be3f7aef5a5f98;
+ 10 dbe0b1ff8673;
+ 10 b26e14c0;
+}
00000000000000000000000000000001
0f1e2d3c4b5a69788796a5b4c3d2e1f0 69bd984641e0aa887bc23738f60070db;
}
+
+square-cmac {
+ f260d7bc
+ ""
+ 29984a33657f622352c1ee581eab804e;
+ da163547
+ d3
+ cdc5e3485007695cdeb53ce1e8cec39e;
+ 48b75511
+ 95e77022907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268eeee533285a6ed810c9b689daaa9060d2d4b6003
+ 7fdd1689e5a004d05b0bc92e3ecc8f16;
+ 062365b0
+ a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd
+ 95f37b226b5f157fb68c9b235085799a;
+ 739a3d1f337f29549e6b0d27
+ ""
+ c48de9e2768ea55c731b65c22052aebd;
+ a4ba234085406a6136512061
+ f7
+ 4710b0fec299631f0d53e9ce3b0a172b;
+ 080cc07df0591d8fa21f2dd8
+ 8374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd47
+ 88eeeecc2b156790ac07c7c4c7b6c431;
+ 05e505da1435dceaa7b1cc49
+ ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a
+ ac18ee08b5e9a21581b33f73b63e9a41;
+ 9b542cde52ebfda1
+ ""
+ d45f57812f3249ba56239bf41459682c;
+ 9d0ccc520f215eb5
+ 7b
+ 12f4a147fd87d19814850cea849fab85;
+ b3a4f3ebbbb18ac6
+ c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b
+ 950e0997bc4188db73c08df2e1e880a6;
+ 69ac26afa3349829
+ b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d156325
+ a1fa99cf13347b5b803ccc6c2e183381;
+}
+
+square-ccm {
+ f260d7bc
+ da163547d348b7551195e7
+ ""
+ ""
+ ""
+ 6f6ddeb0;
+ 7022907d
+ d1dff7dac5c9941d26d0c6
+ eb
+ ""
+ ""
+ bba9ea11;
+ 14ad568f
+ 86edd1dc9268eeee533285
+ ""
+ a6
+ 0a
+ 507bd8ea;
+ ed810c9b
+ 689daaa9060d2d4b60
+ 03062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd
+ 739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a
+ 2de5299d997f5a95d32115f84b8cbc072043580e27bb6ace6654173512e0d464ce4358899c43ac2befe5cbe68155797b
+ 217a8c66edf6aad2f17f555c8936028b;
+ 21635c6d
+ 62c9269029df3e6057
+ acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a8
+ 94476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57b
+ f88c7d34053cc7278c3e3b09715ab3dec3aa050aa70aa6dcd560a9ea58ddd10857b9bcffb98e2af8a3c851f60f540ab8872af0df1d
+ a65b843ead57238ecd6bf0eea46d6fbe;
+ b3a4f3ebbbb18ac6c95a97a4
+ 8030370c33d090c54215ab
+ ""
+ ""
+ ""
+ 345fc32c;
+ d6b3ad54efc9a38378c5b93b
+ f4f2aad2605faee2b03fb6
+ 48
+ ""
+ ""
+ 89dc30e5;
+ e27fff63102758fe2b69ac26
+ afa3349829b94586306fed
+ ""
+ 54
+ ba
+ 595a1d50;
+ 154f8f28523c03d4de160015
+ 7846b710ee72807a22
+ 19bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b
+ 0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a
+ 562758f6a2b849784695d8f36b992eb75a439f9e4daaffff462c1c0e2ed738ae81857040c7bc33093d5d962635b162b3
+ de5af35682b227c7c585fd7ac841b903;
+ 42bb8fdb233bfa6a5cfb0bad
+ 7d95214ade49cb3b6f
+ 5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b
+ 09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d71
+ ef06fd51aee9d8dc17ae50cb1aede6b88f5a5f0e2bfa12f825ef09a757e06a1fd2571bc34e3d6796ea05613d6323cf0ea90dfe15c8
+ efd15ead8ef69008007fb696c5e0de7b;
+ 00b8b649377d20a8
+ f083455b663e4ee1315f3c
+ ""
+ ""
+ ""
+ 6f0d9e5d;
+ 8f2aebfa921451dc
+ d1af5813b70d30ce2f1fef
+ 6e
+ ""
+ ""
+ 76d11bad;
+ f315d0798391805d
+ a08da3aefc5f8584b7c5e6
+ ""
+ 17
+ 0f
+ 8aa0fb43;
+ 669c0f16e39815d4
+ e9cfce3ed1ecdf3d26
+ 4a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986
+ 981a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511
+ b98ec80c9bfcbbf817b03abb770cb6121b7dbf4b497b1af44e9c910bfa324279416423f51b97738f01f27c70436330ef
+ 4d5d0ebb6586b5e8405e66fed4c0361e;
+ 265febd11c164720
+ eef9eb1c8dd0b00951
+ f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc28
+ 10d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c73
+ e948dd0b7f57ae2f94ed538207db42a1f4e3e743aa1105e600284b3b92ce82b4c99ee0a2db8f7f51d17a7084aa068eba1a1f0cd0a7
+ 401f2e64af6c6d18382d1546abe984e4;
+}
+
+square-eax {
+ f260d7bc
+ ""
+ ""
+ ""
+ ""
+ 66848361a1d85500e3efc4889f3c2bd1;
+ da163547
+ d3
+ ""
+ ""
+ ""
+ 3e14f9c0f9b208db9a52730d00525dc6;
+ 48b75511
+ ""
+ 95
+ ""
+ ""
+ 1b81e7698ff5e258ea2e8f75b7bcfd88;
+ e7702290
+ ""
+ ""
+ 7d
+ d5
+ c256dd01d1ee4db1387ef0f0b3d43b57;
+ d1dff7da
+ c5c9941d26d0c6eb14ad568f86edd1dc
+ 9268eeee533285a6ed810c9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137
+ 120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080c
+ cd9fbedf0befc513ec208493902b99f4e304654e0460d29920804d69dc150fa3e31d86a755ba930d0211fee9b7ca5f9f
+ f01b0b0089bf48fedc2c21556a1b644a;
+ c07df059
+ 1d8fa21f2dd88374d8cde8e160ad10
+ 997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da
+ 1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b54
+ b88f48021b69e18d9457120fc11ebdd467c0b1119b5ab0bd16a5c3aa70e263d3ab841cbe6bba4fd02c94690dd143746294f825c26f
+ e0efd3bd220277de49de30272939c21c;
+ 2cde52ebfda19d0ccc520f21
+ ""
+ ""
+ ""
+ ""
+ 8eac437bb3e523a1588a11e05db64b05;
+ 5eb57bb3a4f3ebbbb18ac6c9
+ 5a
+ ""
+ ""
+ ""
+ 8950206e80699724eecfcaa54766d533;
+ 97a48030370c33d090c54215
+ ""
+ ab
+ ""
+ ""
+ ddde409a326fe6d98ce631e1da7f54eb;
+ d6b3ad54efc9a38378c5b93b
+ ""
+ ""
+ f4
+ d8
+ 8288b113a8d26d40aba09cb3f2195dd8;
+ f2aad2605faee2b03fb648e2
+ 7fff63102758fe2b69ac26afa3349829
+ b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b57
+ 1ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f7682
+ 4d1e0a695a91107ecb1d5247d28cfbf19237fc3f63e45f068d11dcbda21d83edcba5bdf9d3f06c2c8cab82fc41bf95dc
+ 530d31b751cdf63e4d3f69dbd3623c8a;
+ 81e040a9b9a222bd689aef66
+ f5306ceb0c6b08ac8b0a22260c571b
+ 4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5
+ b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1d
+ d547e342eb52d40545b00733505c306065b84193dc67ad9436f2acff5224cfe199885811c635803ec7d36a4756a55f97a7d79de113
+ bed4ee2118bb4c7b7a12e34c60b7db7a;
+ ad89d4b9b12012e4
+ ""
+ ""
+ ""
+ ""
+ c2044f9358ab48997b37cd48c3d71ff0;
+ 713df46795630e79
+ 52
+ ""
+ ""
+ ""
+ 7170fe71433b54c9891444470353f8ee;
+ d22bb02d7100b8b6
+ ""
+ 49
+ ""
+ ""
+ 070caac7af2fafb9acbc0dc299952b52;
+ 377d20a8f083455b
+ ""
+ ""
+ 66
+ 91
+ 1871fba93a1bd987dd232ffd84222d45;
+ 3e4ee1315f3c8f2a
+ ebfa921451dcd1af5813b70d30ce2f1f
+ ef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f4
+ 22cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a874498ad0abef8
+ 34bea45625f646aa4fea5c08966df347998c5e91c3e243ddbae6ec95cbd9aef41e52e5bb71cc8d38470075e5f342d0a5
+ b7d0633c6ed773da8c265c633cf8ebcb;
+ bc4fcb70e27e98ef
+ 1f0446b42fb144d44b6d00f06dc188
+ d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331
+ 854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5f
+ b11e564fe1caa81babd189007d9fdf983b4a086302d1eb98daec4f6c91849f873b84982b0a5c037b952355e0a0c916a3967e7ddb69
+ b87b90233e12e003b8ffc0fa198d2269;
+}
+
+square-gcm {
+ f260d7bc
+ ""
+ ""
+ ""
+ ""
+ 66ac17c939ebd05ca617e77ba83201e9;
+ da163547
+ d3
+ ""
+ ""
+ ""
+ 8361e8e723233ce477ef9132624bfb9e;
+ 48b75511
+ ""
+ 95
+ ""
+ ""
+ 29a7e874d6054c42dcc1ada2e6f38cf8;
+ e7702290
+ ""
+ ""
+ 7d
+ 7d
+ d439d2be5e01a0d767739abd80dbc293;
+ d1dff7da
+ c5c9941d26d0c6eb14ad568f86edd1dc
+ 9268eeee533285a6ed810c9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f137
+ 120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080c
+ f36d7d44b8637a2a560a8e89a7a5a5c754de68194a47bb2befdf2384e91eb38cc70807a42a687eb3113c9c223e1c8763
+ e13b8f67d62247d887180b4cfb90eb6b;
+ c07df059
+ 1d8fa21f2dd88374d8cde8e1
+ 60ad10997a21635c6d62c9269029df3e6057ac
+ c87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27
+ 863f1602c0fb45b1a3264e8140b5addd0a82feb9b5e632fc539b3ed83667eecbf32c65dcacec865ea475c3506d61d00db1ba24288ba1a13ef1
+ 58de876618ed18d0aab09ef9acd06bae;
+ 043eb621
+ b7f65b000961040ef2f9b2fc5fa450
+ 727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6
+ b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f8f28523c
+ 1e559d1bc26402ae885ebcb0946a573d44df5d59476510247197bc816467f5386887c5543f3a2256e26f44a91b31afcb7bcc85b2dc
+ 83783d53918eff6b310540ac8c1c5d85;
+ 03d4de1600157846b710ee72
+ ""
+ ""
+ ""
+ ""
+ ddd01942ddf92df99dcada451c651de0;
+ 807a2219bfb474fd71d891f2
+ 4b
+ ""
+ ""
+ ""
+ 85e41566cb1b62bbe5c3e3a2a5f35779;
+ b65d1563259f9eb53b571ea6
+ ""
+ 29
+ ""
+ ""
+ 212a5e2129cd24e177c03718181637d0;
+ c54d57dd2d42f70800df9fcb
+ ""
+ ""
+ ac
+ 28
+ 1b1cb85207cef5e0fe224f9b1d77f836;
+ a48b77dba189196d1ebba10b
+ 0467cb9fc2712a199e533fa9156308cd
+ ec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214a
+ de49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b
+ 2e5f808b009e36fb4f2cf59ec0cdd6f7aac023b9e6037528879a3389aca459a56a337073116aadb30f44453a3bd540df
+ 637a59d017456d0fffea63306283df28;
+ 09c063c46f88de9fd41e72d7
+ b97e23e6eabdff3bcd211499
+ 268878dbf30f1dad89d4b9b12012e4713df467
+ 95630e7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d0798391805d
+ f37ebcd6beca3d239c15bc8e98b774a0c527c87c6fa04ebed3098db72f36ddccba0ee84417d99156b229b6a9b3d6b0d4139233e7d6793618a7
+ a21999c562eaf6d513e48d6a0e12d77c;
+ a08da3aefc5f8584b7c5e617
+ 669c0f16e39815d4e9cfce3ed1ecdf
+ 3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd
+ 52147ed12ca986981a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae98
+ 5e606cf43bfe84c8a64a2ab5d04d377da99053d2dd80b4b9e3b161a04b58b96bc7b750b95fdb479d36cebaebb300526d6d3c8a97e1
+ 7d73467c21c6b79fd07b6670875687f9;
+ 5511265febd11c16
+ ""
+ ""
+ ""
+ ""
+ d06bc05e975b21905cefbf33aed2558b;
+ 4720eef9eb1c8dd0
+ b0
+ ""
+ ""
+ ""
+ 6088d2aa7493efa2bb71465f9b4a4a7f;
+ 0951f284649016ed
+ ""
+ 00
+ ""
+ ""
+ bfc486eed4840dddb9b8eb5cdc0895bb;
+ 456331854bc78bf4
+ ""
+ ""
+ 39
+ 22
+ a44fd42c2bed09a530a167ff512d53c0;
+ 66eb0cfa9138ddc3
+ 9908445608fe95e81c2533e31c9c1a98
+ 51bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717
+ a77456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945f
+ e7ef1f4b63cb4ab8b7ee9c733450f6bf4f921ca5fef77eaebb8cf2fd614e0de3f87e22a59b20f4f7af7af8f9c2175924
+ 1b90917328ea382e254f6d0aa8d8fb50;
+ fd505003cc0cae9c
+ e021a5f1fa4ffa91544485f1
+ a1258b2b9b8f0911e32d65cc1770a18cbfe6ef
+ fd1ff6778554acf1270485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a
+ 90f4bb5b8e60ae32eb97f506c90a0e71156ec2e4a39c1ae669502bbbd6724a3f5713dcdcdacb374f31723a9003a8402dda6b0260362527a72f
+ 2256d08180ac3ed3ab48daa0b86d4cc0;
+ 3e8128f8743d1668
+ 7b7bb8deb9bd205b70e04c091d205c
+ dad9e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d
+ 65bad397abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a5718fd25014107c8
+ 58a997404e629f9e9d5652bd076188c9bd4a631d3e2486a944151f3cf29edbfc62e3910c0b341052b475d623f2339488c9983e0990
+ 1762e398f8582d72954ed718af4f677a;
+}
+
+square-ocb1 {
+ f260d7bc
+ da163547d348b7551195e77022907dd1
+ ""
+ ""
+ ""
+ 4ec5c312526c730e41458aca324ae0a0;
+ dff7dac5
+ c9941d26d0c6eb14ad568f86edd1dc92
+ 68
+ ""
+ ""
+ d0cc24f9084261cdaf4393e7b250701b;
+ eeee5332
+ 85a6ed810c9b689daaa9060d2d4b6003
+ ""
+ 06
+ 72
+ 1e1671f47f5bd8b32ebb09c019105281;
+ 2365b0a5
+ 4364c76c160f11896c4794846ecfa14a
+ ""
+ 7130c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a613651
+ 11e134a63441fc0951b37098764822d6eaa47187fe96a2f3658563cc612c857f0dd5d4e056c820a3670828dd7f5a9d1c
+ 86893621402b0a64fded1b34d47504fb;
+ 2061f708
+ 0cc07df0591d8fa21f2dd88374d8cde8
+ e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd4705e505da14
+ 35dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450
+ 1599b31480519c999bbc9fd4fb1a24676071040c16ff4a6834cdaf46c51ccbb9522cfde0e2df2867871cabd4aa73c33a
+ e8e411a4ac803610a4f2a8e1b6aabba9;
+ 727a9b54
+ 2cde52ebfda19d0ccc520f215eb57bb3
+ ""
+ a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758
+ 384781d5a43f9e0d692787efd9cbbff3f8cc6e154544695653e495e63b3da9730b781b214f5c8f6d940542c76c24f0acacfcf099c0
+ 5fa2cade7fa22e8df91b9f91593f9d3a;
+ fe2b69ac
+ 26afa3349829b94586306fed54154f8f
+ 28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d
+ 57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689a
+ 4c8c3874f73c8504b64bbe612589c103a462720d244c3092221b6c7b31a162aebefaea934d2ac8eb9e03f8f480aa1407d58a8a8e0f
+ 03fa1ede942984e0ae4f30946f7e0201;
+ ef66f5306ceb0c6b08ac8b0a
+ 22260c571b4a42bb8fdb233bfa6a5cfb
+ ""
+ ""
+ ""
+ ae26bcd1fc7065f659ec2e37cdbb4d06;
+ 0bad7d95214ade49cb3b6f5f
+ e8368131115c037ba323fe1dc8151784
+ 87
+ ""
+ ""
+ 9f5a8cdf70fc430a52be4efbe40903b5;
+ 3f0eb5b647da6794c18b5337
+ 685a96ed65b9aca338527ef19b09c063
+ ""
+ c4
+ b1
+ 5358be539c81b8af364ee06a6d510baf;
+ 6f88de9fd41e72d7b97e23e6
+ eabdff3bcd211499268878dbf30f1dad
+ ""
+ 89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dc
+ 6a33c5e3320001aceef2ddb9eb101bc7a44cbbbe05a3a4fffe25cc658d1a5834701a2fd135d964d2aafa112d45c44727
+ a1b70c95ccff432cd7ffac9fcfc36d4b;
+ d1af5813b70d30ce2f1fef6e
+ f315d0798391805da08da3aefc5f8584
+ b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb6
+ 58b970e47479a684b5aefa69a4cd52147ed12ca986981a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b6d
+ 92a2d4564bf2ce07ddfc07a4c61b642f82e07603156c3e67a21fc29958ae1ab0f11689b5361185a5e36e11f8764939c2
+ f4f96b643edc928c53440ca84037253d;
+ 00f06dc188d472a784e0c6f2
+ 1195a3b9f4ae985511265febd11c1647
+ ""
+ 20eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc28
+ 6850774629192af796f0a661a429cfd5a235499b4f839206ab9a23dbeed0566217317c51538556edf394c8d83dffedfa381222d7f6
+ bf6ea195e668f32372ecce468c963344;
+ 10d858cbbc8424d126b807e6
+ daa089c3f9099c5ffb824173d7634c04
+ 226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b73037
+ 4ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65
+ 5016f4b0746fe26e4c8ff63a0fb3a3af5070ba789900e4b69b90c42331d2bef65a6d520ed660c6b8b21180a3e0706e57b6f8e99680
+ 5336c139328f5e30663524991bca106e;
+ cc1770a18cbfe6ef
+ fd1ff6778554acf1270485b203a3c1c4
+ ""
+ ""
+ ""
+ 68289e95ba9adc986ec25334e9821681;
+ c967c0a458cb948b
+ dd409b687fa3a6827b480aa3a4c84cef
+ 64
+ ""
+ ""
+ c3fd1e84842901c9030c844f1cf2a037;
+ f6c9b53bf8f957f4
+ b03cf43e89957f9a3e8128f8743d1668
+ ""
+ 7b
+ 4d
+ 65211e0de7d279e5ecde8793097d5217;
+ 7bb8deb9bd205b70
+ e04c091d205cdad9e9a79b1abf91b085
+ ""
+ 1e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397abfaf529ee41cf9a05c7ef
+ 8cdbd696f4e8b357c8077fd749e4bb0a0f24c8b95deebd0174708f13d6656315c47a9fe9cf561d4afb4e48ab68249248
+ ba46b27e9799540b1f2fed90f8404169;
+ edef3401539c51d2
+ a90bbf7f1bfc338ab0ef5746ea8fdccc
+ d213e33f7e8a5718fd25014107c8e7d715a92add9589d1f5c054b2d983514605ec590294a319b9802068a9f891bc5ba5
+ afabf8c3122d12d7ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2da
+ f227e7487fe14220150b10fa5456bf655b53c2b3cd2200ee882b912d9ad71146f8a937eae0ac4fbdcc99602783caf769
+ 0d78408bce85318de6bcfd8cdc7579ff;
+ c07ecde95759ac46
+ fee6dda7abc8ad68daac90cfe22d2f1f
+ ""
+ 2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4563d405e51881e99027b8ab9aea3ccf860b0009740763d9683
+ 88e08b26d8c6c245d09dedb7a2b2482f0a5816940b89e87ed5c3a0ca573d2b8be39e18d252d84b4d9aad35fc54dbc57306c45676c9
+ 2d9921c55910b5fd930615d61dde717a;
+ 6c5f87b95460938d
+ e1288c69d80ea12ff4bb5f069b8a2e86
+ 041c1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c36800d9645563a308ba60076
+ 817523bd2abf1261b089d8f23a9c2835076a23faac2cdd67771cc667a8331f0a170b66283e4f834a06148f302c3973accd56f6f24e
+ a450198ec39d53163f8db0c90b59a3b5d02dd4ae0c5c800e9b30bb747082e383ffaf85cae517a18ce337b064f74286cf8d843e0696
+ 5a40990ae1dfae2c5cd30d9b32c794c5;
+}
+
+square-pmac1 {
+ f260d7bc
+ ""
+ aec43cacfa9e76ed9f6c0176974d1111;
+ da163547
+ d3
+ 38e2ce3d69f8fb21ed28599d77607fe8;
+ 48b75511
+ 95e77022907dd1dff7dac5c9941d26d0c6eb14ad568f86edd1dc9268eeee533285a6ed810c9b689daaa9060d2d4b6003
+ 7c8785ab3dcb7d71ba3d6fcf7ba32376;
+ 062365b0
+ a54364c76c160f11896c4794846ecfa14a7130c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd
+ b21eb39143554c29a104eb7ca8d10ca8;
+ 739a3d1f337f29549e6b0d27
+ ""
+ 8a5016e4834fa9fe8ef64746a89189ce;
+ a4ba234085406a6136512061
+ f7
+ 21e70bad22188fa3845c86a33d466528;
+ 080cc07df0591d8fa21f2dd8
+ 8374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd47
+ fdb16c9e5914268aa7dca6ee20efb72e;
+ 05e505da1435dceaa7b1cc49
+ ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a
+ c69607969a66a1f0e09c40a8b8e7b303;
+ 9b542cde52ebfda1
+ ""
+ 718839aeaf776c252d578376fe739e46;
+ 9d0ccc520f215eb5
+ 7b
+ 4830cb31ec114ff8704f183f95d06200;
+ b3a4f3ebbbb18ac6
+ c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb648e27fff63102758fe2b
+ c5aa56a0bf29d192de4e3db9174b1b9a;
+ 69ac26afa3349829
+ b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d156325
+ e6d24bd14f25e2fe8909354cdac337f5;
+}
+
+square-ocb3 {
+ f260d7bc
+ da163547d348b7551195e7702290
+ ""
+ ""
+ ""
+ b1669cbf9b59f73b4288eb0761332190;
+ 7dd1dff7
+ dac5c9941d26d0c6eb14ad568f86
+ ed
+ ""
+ ""
+ 780716f09513ecb8dd6f322f3901fd27;
+ d1dc9268
+ eeee533285a6ed810c9b689daaa9
+ ""
+ 06
+ b8
+ 1fcf843450fa4d3da50d8de6525119eb;
+ 0d2d4b60
+ 03062365b0a54364c76c16
+ ""
+ 0f11896c4794846ecfa14a7130c9f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d
+ 33f91dd536f3667b220ac4fa9ef6bec830fc052968f5c3c78141ad56254dbe7fff02e85ea5a278bce0c9a5037caa31f0
+ 11621f557ad6c52a82e8d9495bb284e2;
+ 27a4ba23
+ 4085406a6136512061f7080cc0
+ 7df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3
+ b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7
+ 1859d78e9ad0fbc8bf76a97f08e6de088994238974dce458f7dc145948b8ba9f8b8f52c82a1ff60046350eeec8936379
+ 350f84d218392b1282daa7db5ebc4e5e;
+ f65b0009
+ 61040ef2f9b2fc5fa450727a9b54
+ ""
+ 2cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aa
+ 664cabfb69a25342a0bcc17049c316c78c412df3efbf75cc192b936dccf87b3c094d51468c20911a477cd6a214c403ff99abec313a
+ 09b989eae5e6973b675f06ab4b9ad1e7;
+ d2605fae
+ e2b03fb648e27fff63102758fe2b
+ 69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d8
+ 91f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9
+ 9f53984003391daa1fe81c1e9385d1d902f330b930b225a8164f06adeaff820d08dfceeba9ae1a9639d556bba8ad6563186d022240
+ 64d960c38db07c9ede67bd56b122544e;
+ 156308cdec3f768281e040a9
+ b9a222bd689aef66f5306ceb0c6b
+ ""
+ ""
+ ""
+ c09ceb18e7c3a8ac514ff85bca3ff3c5;
+ 08ac8b0a22260c571b4a42bb
+ 8fdb233bfa6a5cfb0bad7d95214a
+ de
+ ""
+ ""
+ 80ad7d8b14ff64d06b79cd39c7440775;
+ 49cb3b6f5fe8368131115c03
+ 7ba323fe1dc8151784873f0eb5b6
+ ""
+ 47
+ 74
+ 6e58478155a6c0007a0323c4235d8e70;
+ da6794c18b5337685a96ed65
+ b9aca338527ef19b09c063
+ ""
+ c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb0
+ 867bb322577ed2e766f857c22e0114e95c6ffa900fb90bc3937effe8dfa93140d9a58ba0827e5b06c1304ef17fae2c33
+ 0e880f9fe586b0761eb98b29b1636b65;
+ 2d7100b8b649377d20a8f083
+ 455b663e4ee1315f3c8f2aebfa
+ 921451dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3e
+ d1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd5214
+ 738258f0995345cfb20acfae2607aeb91871d5a7b704a82e866350f8e3a28dadef97edc6b7618a12967000642abd3cbe
+ 6a41eed95fa7c3c529eee84ea0a4770a;
+ 7ed12ca986981a874498ad0a
+ bef8bc4fcb70e27e98ef1f0446b4
+ ""
+ 2fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed004563
+ fe2c297cdc8e4761c2d70f8ac5c8431bbdc7560712b651f182aa471c5fa6d9569d0f890c8ab2a5dc6e6e61a130a20d533dc013b6e7
+ 1722ffbd31d1def40cc073828ccc4cfb;
+ 31854bc78bf43966eb0cfa91
+ 38ddc39908445608fe95e81c2533
+ e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4
+ a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6
+ e55a772b18315f4096513d5bf39f4c42665be5375ccee48d7f7c9bb8ad05644e2a2d92b485a2c42514e2abb4940045ed05b2d15bfa
+ 01a830efc22048f44dc01e1db446b5bb;
+ a9f2c0945ffd5050
+ 03cc0cae9ce021a5f1fa4ffa9154
+ ""
+ ""
+ ""
+ 75029ca958d142837b6cd9138b81c0cf;
+ 4485f1a1258b2b9b
+ 8f0911e32d65cc1770a18cbfe6ef
+ fd
+ ""
+ ""
+ 8568e94583082cdd23e3f72b9f28d106;
+ 1ff6778554acf127
+ 0485b203a3c1c4c967c0a458cb94
+ ""
+ 8b
+ 4e
+ 10be6791bce4cff5866df5348e7e9ef3;
+ dd409b687fa3a682
+ 7b480aa3a4c84cef64f6c9
+ ""
+ b53bf8f957f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e
+ 4511dc2330fa5033e1ac63dd1901ed10c5c919a6eed4e953cef5b7847f86f6db03d68301a6dea2c4f8ff6173da5800a7
+ 8bd0072dd3ca8de80eddb1cfca3680fd;
+ 5ca605ac84513995
+ 87011677508a15dde524af3e2b
+ ee0646541a42c2ecccb44d65bad397abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8f
+ dcccd213e33f7e8a5718fd25014107c8e7d715a92add9589d1f5c054b2d983514605ec590294a319b9802068a9f891bc
+ 2212a8678c5de88205f0fea2785f6dbe17d974ff4d64a533c573ca6d9a8079a55bd3241f6783705d81498a2426d522d3
+ 0e895642d052f0695d3ade0d052738cd;
+ 5ba5afabf8c3122d
+ 12d7ff3c41122d70d17d4569eaff
+ ""
+ 59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68daac90cfe22d2f1f29
+ b5e9c68bbf184cfaece73aa7d566a115709a25c94217851433e62f2a28aa9d45a084f521fc5514af2f66c573ce79d817d74a6480b9
+ 613c417ce774d4a717ea6a5fd0ee5b06;
+ 68cc42fa8b669ed3
+ bb3542a9cf44bbc8c6254d980398
+ bd94e66eb4563d405e51881e99027b8ab9aea3ccf860b0009740763d96836c5f87b95460938de1288c69d8
+ 0ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c36800d9645563a308ba600
+ 08a8bccee9fb6b7449fdbd1dfcb6836385770d4f6592e27c563250f869ad4262a87159fc9a0d42b61e1f59acfa244c7bdee8cd03ef
+ f5cf62fa77aba0b2285dc3d231ae2cd5;
+}
+
+square-ocb3-mct {
+ 16 47b0a29f45c1b000f1a0c27eee7f42e7;
+ 12 7a80e7d6e556778f77a327928ff4dc35;
+ 8 886bfcb71cd24995911ed011b231d99e;
+ 4 d0b2597b73f284932af5a5db0fd1fb3d;
+ 16 5c3d0dfbee0d8977a7cee660;
+ 12 6057212ee2684bb36520d44b;
+ 8 5f0f721b8171461d242bb883;
+ 4 127b569653ace9af8aac7f47;
+ 16 4184125b37fbd3fc;
+ 12 258e75d36b5359b3;
+ 8 bd8c4a18f64be7cf;
+ 4 55a5c5e40c4de0e9;
+}
c86c21d8c26dc291f662c8f2fe79b74b 0993d3b68c1d4a5d d33c2e41dd5da131;
af4f4615c7c298639b9728251991419f 1e268f9e710313b5 a9478f8cf88b7e10;
}
+
+tea-cmac {
+ 60d7bcda163547d348b7551195
+ ""
+ c9d9c939fb01921a;
+ e77022907dd1dff7dac5c9941d
+ 26
+ 71bafd3a810cb7fe;
+ d0c6eb14ad568f86edd1dc9268
+ eeee533285a6ed810c9b689daaa9060d2d4b6003062365b0
+ fa579abf1f086cd6;
+ a54364c76c160f11896c479484
+ 6ecfa14a7130c9f137120634c9519848a877ff
+ de36e64b775dcb5c;
+ 77bf79192a5b50
+ ""
+ 7d4dff89fcd86251;
+ ade5d9cd739a3d
+ 1f
+ 8ebb09e514e0fff8;
+ 337f29549e6b0d
+ 27a4ba234085406a6136512061f7080cc07df0591d8fa21f
+ c079db9ba9f93c6d;
+ 2dd88374d8cde8
+ e160ad10997a21635c6d62c9269029df3e6057
+ c57695c67af0e83c;
+ acc87638f508046733d9
+ ""
+ 26c7bc682ced6dd4;
+ ff61cdbda3b3e9878731
+ eb
+ d26aadbc23507937;
+ fedd4705e505da1435dc
+ eaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533
+ 2b121397d4ba05e3;
+ 966f27043eb621b7f65b
+ 000961040ef2f9b2fc5fa450727a9b542cde52
+ 06d48234005d0d34;
+ ebfda19d0ccc520f21
+ ""
+ ddc6b8ce28333159;
+ 5eb57bb3a4f3ebbbb1
+ 8a
+ e5a427c9e3c9b30d;
+ c6c95a97a48030370c
+ 33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad260
+ 3994c72240c20e84;
+ 5faee2b03fb648e27f
+ ff63102758fe2b69ac26afa3349829b9458630
+ ac308d1e150a1c6e;
+}
+
+tea-ccm {
+ 60d7bcda163547d348b7551195
+ e77022
+ ""
+ ""
+ ""
+ 530b9b73;
+ 907dd1dff7dac5c9941d26d0c6
+ eb14ad
+ 56
+ ""
+ ""
+ 0b824023;
+ 8f86edd1dc9268eeee533285a6
+ ed810c
+ ""
+ 9b
+ 61
+ 1cfad40f;
+ 689daaa9060d2d4b6003062365
+ b0a54364c7
+ 6c160f11896c4794846ecfa14a7130c9f137120634c95198
+ 48a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e
+ 9e8ba32c68560a3f15c30cf5a03a842fd9b0fa0efe2cab90
+ 1380f2213a0ab1b6;
+ 6b0d27a4ba234085406a613651
+ 2061f7080c
+ c07df0591d8fa21f2dd88374d8cde8e160ad10
+ 997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbd
+ eb7a05983eb9b9015770af0d2c48f693102f1b74249ce318fb8cc63b25
+ 5624c3dd7fbb9480;
+ a3b3e9878731eb
+ fedd47
+ ""
+ ""
+ ""
+ 4567c460;
+ 05e505da1435dc
+ eaa7b1
+ cc
+ ""
+ ""
+ f8bc87fa;
+ 49ae1d50c38201
+ a89447
+ ""
+ 6b
+ 50
+ e52efea4;
+ 3f102b752eb952
+ 9533966f27
+ 043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542c
+ de52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a
+ 66f563e434c693a453b8d671eb3028567196efe3862247b5
+ 2189a607137658bd;
+ 97a48030370c33
+ d090c54215
+ abd6b3ad54efc9a38378c5b93bf4f2aad2605f
+ aee2b03fb648e27fff63102758fe2b69ac26afa3349829b94586306fed
+ a17d9633a5629dc6336820d8bcdee53caa4989a877fd040f523603f3dd
+ dd98b6ad547d14c2;
+ 54154f8f28523c03d4de
+ 160015
+ ""
+ ""
+ ""
+ 8cd54796;
+ 7846b710ee72807a2219
+ bfb474
+ fd
+ ""
+ ""
+ 4eb0f5a5;
+ 71d891f24bb65d156325
+ 9f9eb5
+ ""
+ 3b
+ d6
+ ed17ae0a;
+ 571ea629c54d57dd2d42
+ f70800df9f
+ cbaca48b77dba189196d1ebba10b0467cb9fc2712a199e53
+ 3fa9156308cdec3f768281e040a9b9a222bd689aef66f530
+ a56c65d5ded200e4794f3478f6774dc80e78ebd4ab58a107
+ 12c12c76eaf729d8;
+ 6ceb0c6b08ac8b0a2226
+ 0c571b4a42
+ bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b
+ 6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b
+ 5fc52790c2df7b9f044c3e6316146e03002f98398cedd18400504685c0
+ 6cc3f23b70f9e36e;
+ 5337685a96ed65b9ac
+ a33852
+ ""
+ ""
+ ""
+ b0ad3d08;
+ 7ef19b09c063c46f88
+ de9fd4
+ 1e
+ ""
+ ""
+ 97501f94;
+ 72d7b97e23e6eabdff
+ 3bcd21
+ ""
+ 14
+ 1a
+ 25f269c4;
+ 99268878dbf30f1dad
+ 89d4b9b120
+ 12e4713df46795630e7952d22bb02d7100b8b649377d20a8
+ f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b7
+ 0d3a7ed00ed5d1408dc96af9770a20b7e9a64569ce57c57a
+ 48de48bb0f882042;
+ 0d30ce2f1fef6ef315
+ d079839180
+ 5da08da3aefc5f8584b7c5e617669c0f16e398
+ 15d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c
+ 41f84b6002f879d39df0797e355cb3a57a3fe6fd635c0daec81ebc831f
+ 79c9b18e32ba64e1;
+}
+
+tea-eax {
+ 60d7bcda163547d348b7551195
+ ""
+ ""
+ ""
+ ""
+ dd6dedcd5275f77b;
+ e77022907dd1dff7dac5c9941d
+ 26
+ ""
+ ""
+ ""
+ 0601c82ec2fc3944;
+ d0c6eb14ad568f86edd1dc9268
+ ""
+ ee
+ ""
+ ""
+ d7f75b8b18dabaab;
+ ee533285a6ed810c9b689daaa9
+ ""
+ ""
+ 06
+ 42
+ 39a3b75cfe30c3e2;
+ 0d2d4b6003062365b0a54364c7
+ 6c160f11896c4794
+ 846ecfa14a7130c9f137120634c9519848a877ff77bf7919
+ 2a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085
+ 0f7263dd0709bb15fa04b8a0a27fe19b40e69596e2f7797d
+ f6a7ce18a023f8e6;
+ 406a6136512061f7080cc07df0
+ 591d8fa21f2dd8
+ 8374d8cde8e160ad10997a21635c6d62c92690
+ 29df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd47
+ ddfb3fac295c9dd9307d5d1464f7b9f9d318b0e3e08fdd6f753b17e248
+ b9850b3a65c973e7;
+ 05e505da1435dc
+ ""
+ ""
+ ""
+ ""
+ dc9b34fb8f76a62c;
+ eaa7b1cc49ae1d
+ 50
+ ""
+ ""
+ ""
+ a3f9e0e94be8cc0e;
+ c38201a894476b
+ ""
+ 3f
+ ""
+ ""
+ a34f5355471f105e;
+ 102b752eb95295
+ ""
+ ""
+ 33
+ ad
+ 53d51c56bd3a3ee2;
+ 966f27043eb621
+ b7f65b000961040e
+ f2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215e
+ b57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215
+ bd62aa1bd2f58df364ecf889d4ede278c68a786cfa817416
+ 69a5bc7134f4df07;
+ abd6b3ad54efc9
+ a38378c5b93bf4
+ f2aad2605faee2b03fb648e27fff63102758fe
+ 2b69ac26afa3349829b94586306fed54154f8f28523c03d4de16001578
+ 345be4b0614ed2b6cee8f1d10f45f48bd6733ffab61b6f5a4fb978b66a
+ 6e7e6f6f73563d4e;
+ 46b710ee72807a2219bf
+ ""
+ ""
+ ""
+ ""
+ 6eedc1098c543339;
+ b474fd71d891f24bb65d
+ 15
+ ""
+ ""
+ ""
+ fb16881264b9b3b2;
+ 63259f9eb53b571ea629
+ ""
+ c5
+ ""
+ ""
+ 753bcc1f76e8e1d2;
+ 4d57dd2d42f70800df9f
+ ""
+ ""
+ cb
+ 1b
+ 3eea24f4c849250a;
+ aca48b77dba189196d1e
+ bba10b0467cb9fc2
+ 712a199e533fa9156308cdec3f768281e040a9b9a222bd68
+ 9aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb23
+ 78cdf18395582eae53580e5c7509bf60c8726dece28af741
+ 5be9c10405f17081;
+ 3bfa6a5cfb0bad7d9521
+ 4ade49cb3b6f5f
+ e8368131115c037ba323fe1dc8151784873f0e
+ b5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c46f88
+ df834e65b1c814814d99f141cdbb8c2d201f47551689b9561f73df1a8d
+ 0b3460ba12e05a4a;
+ de9fd41e72d7b97e23
+ ""
+ ""
+ ""
+ ""
+ 5532b9006b4c1a14;
+ e6eabdff3bcd211499
+ 26
+ ""
+ ""
+ ""
+ 9dc4ef03a759716f;
+ 8878dbf30f1dad89d4
+ ""
+ b9
+ ""
+ ""
+ abd0dd2ce24924b7;
+ b12012e4713df46795
+ ""
+ ""
+ 63
+ e0
+ 5d2cc18653d26e6b;
+ 0e7952d22bb02d7100
+ b8b649377d20a8f0
+ 83455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d
+ 30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5
+ a4321bcfe7f507eeced0ef16c59adb7010401f57d14a172a
+ bb947e016b25ce84;
+ e617669c0f16e39815
+ d4e9cfce3ed1ec
+ df3d264a7f16cb16c2e815f422cdf0c8e30308
+ be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed1
+ 39f472084e8a3a053d250ae58c6a88e6313311f092a388c01ed590e3be
+ 62fab90c78f1e4d7;
+}
+
+tea-gcm {
+ 60d7bcda163547d348b7551195
+ ""
+ ""
+ ""
+ ""
+ 104863c1b7cc0364;
+ e77022907dd1dff7dac5c9941d
+ 26
+ ""
+ ""
+ ""
+ 6824d44998ad5200;
+ d0c6eb14ad568f86edd1dc9268
+ ""
+ ee
+ ""
+ ""
+ 2be3fa8881eb57e1;
+ ee533285a6ed810c9b689daaa9
+ ""
+ ""
+ 06
+ 06
+ 7ccc0eb121d76855;
+ 0d2d4b6003062365b0a54364c7
+ 6c160f11896c4794
+ 846ecfa14a7130c9f137120634c9519848a877ff77bf7919
+ 2a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085
+ ccf001b2a76cd3c5568865d926c0c3c6289456233782bb6d
+ b4afc9476231f8db;
+ 406a6136512061f7080cc07df0
+ 591d8fa2
+ 1f2dd88374d8cde8e160ad
+ 10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9
+ 556dc3cce065e32fd3631b31687e116db7a457f59687e62ec3b9e0f3713456edfd
+ c05e7bc1c66c2194;
+ 878731ebfedd4705e505da1435
+ dceaa7b1cc49ae
+ 1d50c38201a894476b3f102b752eb952953396
+ 6f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52eb
+ 65c59d689cade0038ba31ee851008842af4971efd43a6c0c83b662e9a7
+ 53170fb69a4358c4;
+ fda19d0ccc520f
+ ""
+ ""
+ ""
+ ""
+ 353b4c25eb464d16;
+ 215eb57bb3a4f3
+ eb
+ ""
+ ""
+ ""
+ f0b9141e092436ba;
+ bbb18ac6c95a97
+ ""
+ a4
+ ""
+ ""
+ 5a56e7ab195dff15;
+ 8030370c33d090
+ ""
+ ""
+ c5
+ 63
+ 0ebbd392dd296be9;
+ 4215abd6b3ad54
+ efc9a38378c5b93b
+ f4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26
+ afa3349829b94586306fed54154f8f28523c03d4de160015
+ 89fbccd054ce4e0e729a9348449702044abe666342d15dee
+ 09c94f26212a5c9c;
+ 7846b710ee7280
+ 7a2219bf
+ b474fd71d891f24bb65d15
+ 63259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebb
+ 62666b6deb78f4ca61a19405496b18f9af1e6c16c03eeafed378c6c14dc2760f87
+ 5c37f56a50aad8ba;
+ a10b0467cb9fc2
+ 712a199e533fa9
+ 156308cdec3f768281e040a9b9a222bd689aef
+ 66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad
+ e44a6687f1516bda0c8403c0befbf7537a4cf036dcdcfd96e11d2dfda4
+ 26338cb7a4856da3;
+ 7d95214ade49cb3b6f5f
+ ""
+ ""
+ ""
+ ""
+ d2ea2800e7d48c03;
+ e8368131115c037ba323
+ fe
+ ""
+ ""
+ ""
+ 9f49f14465230250;
+ 1dc8151784873f0eb5b6
+ ""
+ 47
+ ""
+ ""
+ 1844b6087e8cca0f;
+ da6794c18b5337685a96
+ ""
+ ""
+ ed
+ 8f
+ 7aa8c91ba90be3c4;
+ 65b9aca338527ef19b09
+ c063c46f88de9fd4
+ 1e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89
+ d4b9b12012e4713df46795630e7952d22bb02d7100b8b649
+ d493f349ac86d68f2b5a119280b7e849a4fc67d29b952c51
+ edf814101fdece49;
+ 377d20a8f083455b663e
+ 4ee1315f
+ 3c8f2aebfa921451dcd1af
+ 5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f
+ 72fde1faae8cceca80d4d76992f2636732bd05609713442fbf159576f9cb844e91
+ c654365e3cecad77;
+ 16e39815d4e9cfce3ed1
+ ecdf3d264a7f16
+ cb16c2e815f422cdf0c8e30308be3c31e6bc58
+ c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a87
+ e28f18dcf71cfb49b094dac380189402100d4256169995d2f33dce3e77
+ c86e61eec92dda36;
+ 4498ad0abef8bc4fcb
+ ""
+ ""
+ ""
+ ""
+ 4b7087b7ee345d6c;
+ 70e27e98ef1f0446b4
+ 2f
+ ""
+ ""
+ ""
+ 9c586b9f2a4a8338;
+ b144d44b6d00f06dc1
+ ""
+ 88
+ ""
+ ""
+ f9c5a60277aba1ef;
+ d472a784e0c6f21195
+ ""
+ ""
+ a3
+ 01
+ 0546d37e096d7325;
+ b9f4ae985511265feb
+ d11c164720eef9eb
+ 1c8dd0b00951f284649016ed00456331854bc78bf43966eb
+ 0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc
+ c579381ec4d7849aa0c7959d8b5fa316430a709bf6949cbb
+ 479c8f6f98bf9a02;
+ 2810d858cbbc8424d1
+ 26b807e6
+ daa089c3f9099c5ffb8241
+ 73d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db
+ 6aa3da0c805ece511ebb54408d1529d4d5f993373fbba6425692a5a643b6e6cf5d
+ f2b2f11c0f79c16c;
+ 8f48af65f7cc9e3fb9
+ 0e1721b730374f
+ fc9bc597f56ccbb2f294b38766fc69f6a9f2c0
+ 945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f09
+ ee503d12aef7e05140a33551f93a02eb6631e56e47a61f61b5357a4636
+ 4f584686113ded23;
+}
+
+tea-ocb1 {
+ 60d7bcda163547d348b7551195
+ e77022907dd1dff7
+ ""
+ ""
+ ""
+ 0282d13eb3775978;
+ dac5c9941d26d0c6eb14ad568f
+ 86edd1dc9268eeee
+ 53
+ ""
+ ""
+ 9b0cdcfa8c04a747;
+ 3285a6ed810c9b689daaa9060d
+ 2d4b6003062365b0
+ ""
+ a5
+ 3b
+ cdfabcc04b5d33e6;
+ 4364c76c160f11896c4794846e
+ cfa14a7130c9f137
+ ""
+ 120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d
+ 68cf0d4fc52e5f441683c80bdaac28743382b75271027f73
+ 10e9f17c3d7446da;
+ 1f337f29549e6b0d27a4ba2340
+ 85406a6136512061
+ f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a
+ 21635c6d62c9269029df3e6057acc87638f508046733d9ff
+ f5899357e4d68a1947927de3a88c20b0a372611945f68d3a
+ 172008bf86d64904;
+ 61cdbda3b3e9878731ebfedd47
+ 05e505da1435dcea
+ ""
+ a7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb6
+ 1871ca08dc9d4856d3181c8a16b9a5284e727cc4c21ee458e65a7ede72
+ 400b866405f8cca1;
+ 21b7f65b000961040ef2f9b2fc
+ 5fa450727a9b542c
+ de52ebfda19d0ccc520f215eb57bb3a4f3ebbb
+ b18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b9
+ 8845244bc553c66cbcd7398a529004c22b7bc44b8c12ee1cdae4b9964f
+ 11437ce8e831d965;
+ 3bf4f2aad2605f
+ aee2b03fb648e27f
+ ""
+ ""
+ ""
+ b24fea9cbe55c7cf;
+ ff63102758fe2b
+ 69ac26afa3349829
+ b9
+ ""
+ ""
+ 172ba721b939b9e3;
+ 4586306fed5415
+ 4f8f28523c03d4de
+ ""
+ 16
+ 56
+ 8f3914c03d77623e;
+ 00157846b710ee
+ 72807a2219bfb474
+ ""
+ fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d
+ 1f489e532c4895221fb87757559418ebdbb80731a4d433ca
+ aee9886723bcf8c2;
+ 42f70800df9fcb
+ aca48b77dba18919
+ 6d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f76
+ 8281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22
+ 003b1897c5b5c2a68a1061f67ab282ba4f5bc1d5b69dff33
+ d5d03c8ceb5dedad;
+ 260c571b4a42bb
+ 8fdb233bfa6a5cfb
+ ""
+ 0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc815178487
+ 616c9b723ce2dbf6582926c0082396983b36136650dbe54d4034e80c81
+ f272e48012ecedb1;
+ 3f0eb5b647da67
+ 94c18b5337685a96
+ ed65b9aca338527ef19b09c063c46f88de9fd4
+ 1e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012
+ 61107d0d71b63c91fc60d6981a7b027175f951198ead98054f3c891a56
+ f0b7270b5db81fec;
+ e4713df46795630e7952
+ d22bb02d7100b8b6
+ ""
+ ""
+ ""
+ 8ec34345774654fe;
+ 49377d20a8f083455b66
+ 3e4ee1315f3c8f2a
+ eb
+ ""
+ ""
+ 9752407ae0186131;
+ fa921451dcd1af5813b7
+ 0d30ce2f1fef6ef3
+ ""
+ 15
+ 81
+ 1beb2958c9f181a1;
+ d0798391805da08da3ae
+ fc5f8584b7c5e617
+ ""
+ 669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e8
+ 76b4c7ff71df213ad4bacdd80c69f7e6dea704bfc63d27ba
+ dbdc98bafb6d3cd3;
+ 15f422cdf0c8e30308be
+ 3c31e6bc58c0b7ca
+ dcb658b970e47479a684b5aefa69a4cd52147ed12ca98698
+ 1a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d4
+ aff8e168c9ca00f7a3686535f2c3a87b87554ef97829cfdc
+ 5a0258fedb40c24f;
+ 4b6d00f06dc188d472a7
+ 84e0c6f21195a3b9
+ ""
+ f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00
+ b9d9161aaec022635a134ed7847aec38d0c8903ef455fa741bf671369b
+ 625dbf5d69c3e31e;
+ 456331854bc78bf43966
+ eb0cfa9138ddc399
+ 08445608fe95e81c2533e31c9c1a9851bc2810
+ d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f
+ 8a2521cc4a159578267a2501822161dab72ff8663eeb7c0216e8e372cb
+ 74098a7f405219bd;
+ 30cbb7f0e4a973a8cd
+ 190107314717a774
+ ""
+ ""
+ ""
+ ea4da20a4cb1c61f;
+ 56f3ff669c732b58db
+ 8f48af65f7cc9e3f
+ b9
+ ""
+ ""
+ 0db86f6d6832d301;
+ 0e1721b730374ffc9b
+ c597f56ccbb2f294
+ ""
+ b3
+ 32
+ 7275eb9aee00342a;
+ 8766fc69f6a9f2c094
+ 5ffd505003cc0cae
+ ""
+ 9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65
+ d09b91ddba2620cd1a4a7fe88de8c22ef06be7a9b1627b4b
+ b37e8c04b73654d2;
+ cc1770a18cbfe6effd
+ 1ff6778554acf127
+ 0485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b
+ 480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a
+ 962273e83ac507e225ed07a9fce44bf2dbaad409592ebd49
+ 0a77a4eaf298a242;
+ 3e8128f8743d16687b
+ 7bb8deb9bd205b70
+ ""
+ e04c091d205cdad9e9a79b1abf91b0851e5ca605ac8451399587011677
+ 795b6ec2108ac4cbda8b87ede294541cfdb7240cfae8ff7a4d9a474ea5
+ 798360c72cf9d7d0;
+ 508a15dde524af3e2b
+ ee0646541a42c2ec
+ ccb44d65bad397abfaf529ee41cf9a05c7efed
+ ef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a
+ f0d9c8a507a51d66a13e9cd477b177773ff6f94dbda67dbf07003162ab
+ 70ddae5e6ffa478f;
+}
+
+tea-pmac1 {
+ 60d7bcda163547d348b7551195
+ ""
+ 25bca2fe99e75c4b;
+ e77022907dd1dff7dac5c9941d
+ 26
+ 5b87dc7b2acac1be;
+ d0c6eb14ad568f86edd1dc9268
+ eeee533285a6ed810c9b689daaa9060d2d4b6003062365b0
+ 6889c9fb6030676d;
+ a54364c76c160f11896c479484
+ 6ecfa14a7130c9f137120634c9519848a877ff
+ 453581670da49ebe;
+ 77bf79192a5b50
+ ""
+ 613c5d3427421aa4;
+ ade5d9cd739a3d
+ 1f
+ 39649926ad4cd68d;
+ 337f29549e6b0d
+ 27a4ba234085406a6136512061f7080cc07df0591d8fa21f
+ 24043405966f7f84;
+ 2dd88374d8cde8
+ e160ad10997a21635c6d62c9269029df3e6057
+ 8242433c45487ffe;
+ acc87638f508046733d9
+ ""
+ f24ce66e0a3a63d2;
+ ff61cdbda3b3e9878731
+ eb
+ 8bdfb1992aed4edf;
+ fedd4705e505da1435dc
+ eaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533
+ ee6d2bd9a43a054a;
+ 966f27043eb621b7f65b
+ 000961040ef2f9b2fc5fa450727a9b542cde52
+ 936eb156c9146198;
+ ebfda19d0ccc520f21
+ ""
+ c33c9c35b8f3836e;
+ 5eb57bb3a4f3ebbbb1
+ 8a
+ ac3f52785c36bf6f;
+ c6c95a97a48030370c
+ 33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad260
+ 1a935b87b899b277;
+ 5faee2b03fb648e27f
+ ff63102758fe2b69ac26afa3349829b9458630
+ df79e3c4601f609a;
+}
+
+tea-ocb3 {
+ 60d7bcda163547d348b7551195
+ e77022907dd1
+ ""
+ ""
+ ""
+ 50e56f25fe9fa75a;
+ dff7dac5c9941d26d0c6eb14ad
+ 568f86edd1dc
+ 92
+ ""
+ ""
+ b018725e1da1fc14;
+ 68eeee533285a6ed810c9b689d
+ aaa9060d2d4b
+ ""
+ 60
+ 94
+ bce5f4718c762d22;
+ 03062365b0a54364c76c160f11
+ 896c47
+ ""
+ 94846ecfa14a7130c9f137120634c9519848a877ff77bf79
+ f63c61926eb91517997efd1a280da07726f45280bd3d5893
+ ce2fa9afb1a39afb;
+ 192a5b50ade5d9cd739a3d1f33
+ 7f29549e6b
+ 0d27a4ba234085406a6136512061f7080cc07df0591d8fa2
+ 1f2dd88374d8cde8e160ad10997a21635c6d62c9269029df
+ 3f60ebe2319bfad8b557bcd414b60e89212bbeea2a5c4373
+ 74e2d32d1767921c;
+ 3e6057acc87638f508046733d9
+ ff61cdbda3b3
+ ""
+ e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a89447
+ b04de9996b330715ff382cfec0333bfd66421410bf16459d12a0f28f53
+ 38b0c98a1f1ec6da;
+ 6b3f102b752eb9529533966f27
+ 043eb621b7f6
+ 5b000961040ef2f9b2fc5fa450727a9b542cde
+ 52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c
+ f7e226026675e1adc5cf37952abccc77b8154368557b87ec40477620f8
+ 44b45cf50973cb50;
+ 33d090c54215ab
+ d6b3ad54efc9
+ ""
+ ""
+ ""
+ 1eb02bffdd9d7dc6;
+ a38378c5b93bf4
+ f2aad2605fae
+ e2
+ ""
+ ""
+ 58ee8252984db2d4;
+ b03fb648e27fff
+ 63102758fe2b
+ ""
+ 69
+ d4
+ 961e871fd84b5a74;
+ ac26afa3349829
+ b94586
+ ""
+ 306fed54154f8f28523c03d4de1600157846b710ee72807a
+ 0e6295372bd9df61b2ca8d2a383154e2c70fd3ca68805de6
+ b8a6cce0dd7f6222;
+ 2219bfb474fd71
+ d891f24bb6
+ 5d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcb
+ aca48b77dba189196d1ebba10b0467cb9fc2712a199e533f
+ fd0562d5b003e68f0d1d72c4e082b87827f85ee88b52cd87
+ 1e835d35eb0cd334;
+ a9156308cdec3f
+ 768281e040a9
+ ""
+ b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb23
+ 41c1cd96958e4f6ffaa16db2ec8a521140e548564fccdfb890ab8939f0
+ 56271f56c7ea11ed;
+ 3bfa6a5cfb0bad
+ 7d95214ade49
+ cb3b6f5fe8368131115c037ba323fe1dc81517
+ 84873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c0
+ fc1d24d91e4ab2c51590e2a94796bf4da4a50a6c07e20a40fb1981d17a
+ c8e3e3fd09cfb494;
+ 63c46f88de9fd41e72d7
+ b97e23e6eabd
+ ""
+ ""
+ ""
+ b222e91b3dfc4b68;
+ ff3bcd211499268878db
+ f30f1dad89d4
+ b9
+ ""
+ ""
+ ceaecf08444b8cd3;
+ b12012e4713df4679563
+ 0e7952d22bb0
+ ""
+ 2d
+ a2
+ d537e5734f7de7da;
+ 7100b8b649377d20a8f0
+ 83455b
+ ""
+ 663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f
+ 4020ccd7a166229e19cd4c48b61701120098e7dad7780102
+ ef64295063a916fa;
+ 1fef6ef315d079839180
+ 5da08da3ae
+ fc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d
+ 264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0
+ 07c0c12b3fad029d165bb6b6a9363c7699a27081a8aaf72b
+ f984336df824fe7e;
+ b7cadcb658b970e47479
+ a684b5aefa69
+ ""
+ a4cd52147ed12ca986981a874498ad0abef8bc4fcb70e27e98ef1f0446
+ c19e2396ffc0dd7c73a0f53b39e90139179cefc32e75f8d50f5f627a39
+ 2a57fec6502d09d9;
+ b42fb144d44b6d00f06d
+ c188d472a784
+ e0c6f21195a3b9f4ae985511265febd11c1647
+ 20eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0c
+ 3fb5c778395cfbfbd94d6707cb18520f9b95b101e5f1673248f37afb8f
+ 01ba4da3facd1ec8;
+ fa9138ddc399084456
+ 08fe95e81c25
+ ""
+ ""
+ ""
+ ef931af545c454ab;
+ 33e31c9c1a9851bc28
+ 10d858cbbc84
+ 24
+ ""
+ ""
+ c24d1e102b084b5e;
+ d126b807e6daa089c3
+ f9099c5ffb82
+ ""
+ 41
+ e8
+ 3b28cf6d12081293;
+ 73d7634c04226f30cb
+ b7f0e4
+ ""
+ a973a8cd190107314717a77456f3ff669c732b58db8f48af
+ 27a3f2e9c0dbf9ee78fe2eaea691734d96105ec04619032b
+ 552e65ed80338e08;
+ 65f7cc9e3fb90e1721
+ b730374ffc
+ 9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003
+ cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911
+ 45aa335db92540c2bcd0ec28dd97d101c4e14776c4fd1d04
+ fa2cf5a4f20122ef;
+ e32d65cc1770a18cbf
+ e6effd1ff677
+ ""
+ 8554acf1270485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b
+ 44c70463fafaed7e9b3de27cf5c92511a88eeaf9453b1da16914f9c61c
+ 62e9efc911c2b6d8;
+ 480aa3a4c84cef64f6
+ c9b53bf8f957
+ f4b03cf43e89957f9a3e8128f8743d16687b7b
+ b8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac84
+ d848b6c4ea2e04b8599c41fa786fbac28cbef5ab4039415ca71d4678c7
+ 19c2d53e7566afc7;
+}
+
+tea-ocb3-mct {
+ 16 cb326883e2a7abc7;
+ 14 129631272316ca86;
+ 12 c0a6fdaab85e1578;
+ 10 112f7058a53b3c59;
+ 8 786b90684bfe1e77;
+ 6 842c674eb1cff4ed;
+ 4 f1319ace9cb4027c;
+ 16 fd0cc4fec30a;
+ 14 215b15aeab0e;
+ 12 f23528992843;
+ 10 48cacf15625e;
+ 8 74b0608cc983;
+ 6 d0dd11b11aa8;
+ 4 1960a6aa86d6;
+ 16 b9865f9f;
+ 14 6f09a6bc;
+ 12 b32b1dc6;
+ 10 13e1a721;
+ 8 b5aefa26;
+ 6 c2c46207;
+ 4 b0bf9065;
+}
--- /dev/null
+### Local tests for Twofish.
+
+twofish-cmac {
+ 60d7bcda163547d348b7551195
+ ""
+ 754e3b8b4c2532dd6d26b8d2f84c5052;
+ e77022907dd1dff7dac5c9941d
+ 26
+ 285e8d83398954587754b4811af4dab0;
+ d0c6eb14ad568f86edd1dc9268
+ eeee533285a6ed810c9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f1371206
+ 8f5bfbfe9492043376e871ff2174ab5b;
+ 34c9519848a877ff77bf79192a
+ 5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd8
+ 1145ad608df01125e831efceb693c24b;
+ 8374d8cde8e160ad10997a21
+ ""
+ 1406392a843cc373790cd8696e89d1ea;
+ 635c6d62c9269029df3e6057
+ ac
+ 70ba3b7789c8bae0f1f51219e9730125;
+ c87638f508046733d9ff61cd
+ bda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb6
+ 6fa25a24102c74af333d7d00e814c926;
+ 21b7f65b000961040ef2f9b2
+ fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c5
+ fa27b530c2b27564a3be2411d2eca2ff;
+ 4215abd6b3ad54ef
+ ""
+ ed98c8e1a4135fa9bbde6733062c0be7;
+ c9a38378c5b93bf4
+ f2
+ ebc7a731525279b9f3432af13aa735d1;
+ aad2605faee2b03f
+ b648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219
+ ad157b3ad3c9b514307a6075859baa83;
+ bfb474fd71d891f2
+ 4bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9f
+ 2c6b7e9737106b483e1ca8497e995b5a;
+ c2712a199e533fa9156308cdec3f768281
+ ""
+ 0b25455053592925387a5cab03aa3418;
+ e040a9b9a222bd689aef66f5306ceb0c6b
+ 08
+ 795defa6334cf18ed76ffa59a9ef6500;
+ ac8b0a22260c571b4a42bb8fdb233bfa6a
+ 5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65
+ 7a1639ba51eb2aeaf469d4980148378f;
+ b9aca338527ef19b09c063c46f88de9fd4
+ 1e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d
+ dabc6ab5c4f7051e8211bcafd27650f6;
+}
+
+twofish-ccm {
+ 60d7bcda163547d348b7551195
+ e77022907dd1dff7dac5c9
+ ""
+ ""
+ ""
+ b0c9e428;
+ 941d26d0c6eb14ad568f86edd1
+ dc9268eeee533285a6ed81
+ 0c
+ ""
+ ""
+ 68f3bf5a;
+ 9b689daaa9060d2d4b60030623
+ 65b0a54364c76c160f1189
+ ""
+ 6c
+ c6
+ 30270248;
+ 4794846ecfa14a7130c9f13712
+ 0634c9519848a877ff
+ 77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd8
+ 8374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd47
+ f3d43c102dc21b52ba97431dbe9d96795b0c6d04920b5477e6ebf4706786e1bb6bf172fa749e9f62041c7b697875d4ee
+ 89a2a9f68c8a775f6d0ad66e43bfc2b5;
+ 05e505da1435dceaa7b1cc49ae
+ 1d50c38201a894476b
+ 3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0c
+ cc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad2605faee2b03fb6
+ 13d35753fc8ea503aa2f2ce83e66c54c392aeab215aacd566043634da890cac0f81e7318c2640f2ccbdf691baf4e36e42d48a992a2
+ 0337b188fc02b7868b5f6c0b9c462f44;
+ 48e27fff63102758fe2b69ac
+ 26afa3349829b94586306f
+ ""
+ ""
+ ""
+ f3b74c76;
+ ed54154f8f28523c03d4de16
+ 00157846b710ee72807a22
+ 19
+ ""
+ ""
+ 0efb24c2;
+ bfb474fd71d891f24bb65d15
+ 63259f9eb53b571ea629c5
+ ""
+ 4d
+ fc
+ 2f1984e1;
+ 57dd2d42f70800df9fcbaca4
+ 8b77dba189196d1ebb
+ a10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c57
+ 1b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da67
+ 6a399a08440ac7cb9d502c9f52a33d1df8ee9681bab13cfa2cae7aaeb82071cd7c99df8f768be5f910cf8db83e09f14c
+ 2ed58e267c0b2588e3910f0c31b961d3;
+ 94c18b5337685a96ed65b9ac
+ a338527ef19b09c063
+ c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e
+ 7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d079839180
+ 7aa91272a3c0c35156125064eb307c2e5bfe698266b7effff016afe64776bcc38d6965424f882285c418a92f480c24c59fcb2c1f79
+ 6b3f9910b25e356ecfac4863fcee37d3;
+ 5da08da3aefc5f85
+ 84b7c5e617669c0f16e398
+ ""
+ ""
+ ""
+ b17a3a3d;
+ 15d4e9cfce3ed1ec
+ df3d264a7f16cb16c2e815
+ f4
+ ""
+ ""
+ d95d0468;
+ 22cdf0c8e30308be
+ 3c31e6bc58c0b7cadcb658
+ ""
+ b9
+ c7
+ 0ef68941;
+ 70e47479a684b5ae
+ fa69a4cd52147ed12c
+ a986981a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae98
+ 5511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608
+ b0710f1564a118168643f2365349548ad8955fb798437ec62b9b3005d68ffc8e50ea0b92e3c7fe92c0c0660ec9945182
+ e2d3128d41c1f5f53fd1727fe0b0b097;
+ fe95e81c2533e31c
+ 9c1a9851bc2810d858
+ cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717a7
+ 7456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0c
+ fc551743341d475b9daee5768d456ab9a1e4c4156650b10689702560de27cc285a543e06e6f0b8e3e2868deba6ea47016e54a72bf5
+ 169d69aa85a8d2806a324ea9568094fd;
+ ae9ce021a5f1fa4ffa91544485f1a1258b
+ 2b9b8f0911e32d65cc1770
+ ""
+ ""
+ ""
+ eb7833ed;
+ a18cbfe6effd1ff6778554acf1270485b2
+ 03a3c1c4c967c0a458cb94
+ 8b
+ ""
+ ""
+ 2d96cd56;
+ dd409b687fa3a6827b480aa3a4c84cef64
+ f6c9b53bf8f957f4b03cf4
+ ""
+ 3e
+ 12
+ 5739e99a;
+ 89957f9a3e8128f8743d16687b7bb8deb9
+ bd205b70e04c091d20
+ 5cdad9e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397
+ abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a5718fd25014107
+ 9a42a39fcbb079b601c9a0169b11a7bda9592f85ee47a7cebf8be2dad4157356aedf18d3c792446f2439a0cf0d95e7f7
+ 37724239996c480fc49e7e43a84458bc;
+ c8e7d715a92add9589d1f5c054b2d98351
+ 4605ec590294a319b9
+ 802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe079753ee
+ 1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44
+ 0dd51ef8b16e3923be6906378e726f6e9d4b79b815fdad7282db135ee1d65a9b89f08c2976c77be0c5d76cdc530cfe077e71bfac9b
+ d086f21e917aa8b0152b51116a8d72af;
+}
+
+twofish-eax {
+ 60d7bcda163547d348b7551195
+ ""
+ ""
+ ""
+ ""
+ 9c340a7f586dfd6561333d865d3be637;
+ e77022907dd1dff7dac5c9941d
+ 26
+ ""
+ ""
+ ""
+ b49707150b501a9aeb08849a8ce835c5;
+ d0c6eb14ad568f86edd1dc9268
+ ""
+ ee
+ ""
+ ""
+ 7c390db5bff614ee888d1b5a9d58a08f;
+ ee533285a6ed810c9b689daaa9
+ ""
+ ""
+ 06
+ 19
+ 747cff93ab194812482ac265aae10c05;
+ 0d2d4b6003062365b0a54364c7
+ 6c160f11896c4794846ecfa14a7130c9
+ f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7
+ 080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61
+ dd91fa89b463675215e5bf946e26d943bec9f16b85ab13386e59e241b8040179b9434123c3f18a91db1ca422e5ec4589
+ 2516f3bef1bc5bc211b49bed94687265;
+ cdbda3b3e9878731ebfedd4705
+ e505da1435dceaa7b1cc49ae1d50c3
+ 8201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde
+ 52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad260
+ edf0e0b4ca907432f7c994c4d185aa3db5d998ad1911852793c31f1e08c8a0facb5b743188745f1f1f0a3b5cb459a49b6568ade9d9
+ a8755cc0ba6d7951c1e462f3d7488839;
+ 5faee2b03fb648e27fff6310
+ ""
+ ""
+ ""
+ ""
+ fabb71671ec2e89032276be01704ef69;
+ 2758fe2b69ac26afa3349829
+ b9
+ ""
+ ""
+ ""
+ 560eafd0ed251ac82b143a85f180b657;
+ 4586306fed54154f8f28523c
+ ""
+ 03
+ ""
+ ""
+ 94fafa14c9819062fb631fb20d784aed;
+ d4de1600157846b710ee7280
+ ""
+ ""
+ 7a
+ a8
+ db105495b660dbd22506ea66be1d09d5;
+ 2219bfb474fd71d891f24bb6
+ 5d1563259f9eb53b571ea629c54d57dd
+ 2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222
+ bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe836813111
+ 947c775e1a6deb3042c702a3600473796bebeb264ff0594b0352a85491239c812fa2f3c21d458e2b5b784625e5f8cc32
+ 8e0728b45016d6178f32ee80773b72d0;
+ 5c037ba323fe1dc815178487
+ 3f0eb5b647da6794c18b5337685a96
+ ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89
+ d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d
+ 1d131416240ea96f731942579422e18acb633d0429a46d31b64ff5f24f8ee6bb05769731eaf0da2725da3204f04820baf228831c09
+ e21621e777b6283f5fbb2095f4d9a668;
+ 30ce2f1fef6ef315
+ ""
+ ""
+ ""
+ ""
+ 52512330b00f2450fdfcb97d554ac098;
+ d0798391805da08d
+ a3
+ ""
+ ""
+ ""
+ 58800f1e6613f646fe7e562590c3de9f;
+ aefc5f8584b7c5e6
+ ""
+ 17
+ ""
+ ""
+ 72cb0d5710a6a99ba7618544108409ad;
+ 669c0f16e39815d4
+ ""
+ ""
+ e9
+ 69
+ 05f8ecb88a66f4a0289e5e3d04bddbe7;
+ cfce3ed1ecdf3d26
+ 4a7f16cb16c2e815f422cdf0c8e30308
+ be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a874498ad0abef8bc4fcb70e27e98
+ ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb1c8dd0b009
+ 772117eeb7a3c0f1901d15bb4cd5aa2bbcc21c8900e9a590918c1278893bf93d6e10908d6aa0a3844de33ae47ef11fbf
+ 463ada14035a59434547a76404af4ee6;
+ 51f284649016ed00
+ 456331854bc78bf43966eb0cfa9138
+ ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb82
+ 4173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3fb90e1721b730374ffc9bc5
+ 5f7a453a5988894d4c010d0c1d61c46e0fdac102b82d40e60fd88fa2a733048be1adc091040977c1ce28b608f3b47f541316a51382
+ b3e874d11f8b935d338bd549a4d8158a;
+ 97f56ccbb2f294b38766fc69f6a9f2c094
+ ""
+ ""
+ ""
+ ""
+ 522cec98b8703b39bdef4b7b71100e69;
+ 5ffd505003cc0cae9ce021a5f1fa4ffa91
+ 54
+ ""
+ ""
+ ""
+ 9696c681b07c07a545c546a9698822fb;
+ 4485f1a1258b2b9b8f0911e32d65cc1770
+ ""
+ a1
+ ""
+ ""
+ e99931b41ebf63d52cb833b03c3f6ea4;
+ 8cbfe6effd1ff6778554acf1270485b203
+ ""
+ ""
+ a3
+ 53
+ c4f447d9deadfeb7916af9eb906f838d;
+ c1c4c967c0a458cb948bdd409b687fa3a6
+ 827b480aa3a4c84cef64f6c9b53bf8f9
+ 57f4b03cf43e89957f9a3e8128f8743d16687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac
+ 8451399587011677508a15dde524af3e2bee0646541a42c2ecccb44d65bad397abfaf529ee41cf9a05c7efedef340153
+ ca3c5595f62889c4f242ac0da256bf103ca30908909139a4d43b0baa411a6fe47f8daf20b32bcba14f482f76b888265b
+ 041cf6ef9deec56c1bba923f276f8d75;
+ 9c51d2a90bbf7f1bfc338ab0ef5746ea8f
+ dcccd213e33f7e8a5718fd25014107
+ c8e7d715a92add9589d1f5c054b2d983514605ec590294a319b9802068a9f891bc5ba5afabf8c3122d12d7
+ ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7ab
+ 1cc781e5396ac8524f32f3a2e1dd087ce19381548225aa1d043499e04890a78ba1c21cad856ff355265a9760b6f81ba5a9b34d275f
+ bb1cd29c56a26e0a9ef3fc8341f8f663;
+}
+
+twofish-gcm {
+ 60d7bcda163547d348b7551195
+ ""
+ ""
+ ""
+ ""
+ 7e0c01ab8086fe01a7c940e3d5e4c825;
+ e77022907dd1dff7dac5c9941d
+ 26
+ ""
+ ""
+ ""
+ 03cc1ef1b342e6882d46938c5583bcde;
+ d0c6eb14ad568f86edd1dc9268
+ ""
+ ee
+ ""
+ ""
+ 922c01776999bb27557eaff4621e6542;
+ ee533285a6ed810c9b689daaa9
+ ""
+ ""
+ 06
+ 2d
+ 65db54152b66c0a4630723dad69c59fe;
+ 0d2d4b6003062365b0a54364c7
+ 6c160f11896c4794846ecfa14a7130c9
+ f137120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7
+ 080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61
+ d2fd5ce98fff00c787eec5ba7c1428b7e298c61467e66996e9e34dd9f98e9dcb9e272339bcd0b5e261887f4a735d14e5
+ bdee54527341a497d08ead912a0fd02b;
+ cdbda3b3e9878731ebfedd4705
+ e505da1435dceaa7b1cc49ae
+ 1d50c38201a894476b3f102b752eb952953396
+ 6f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33
+ 7666e42e7493950c9783e8b919586b513c70b5ac09fcfcdd0a7199a12fded4b8c7499bc5803a2eb9c0e3934a4f42ff8fe32fad10326556567e
+ c341241121b63236496060eef63ffe36;
+ d090c54215abd6b3ad54efc9a3
+ 8378c5b93bf4f2aad2605faee2b03f
+ b648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee
+ 72807a2219bfb474fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b04
+ 5f0cf7d078722238b7aaac66bf90a3a9761e66f896d956d9414d54a425e983126667ab8b776f1363fc275661175db1ee73d5529c59
+ 0e29764305b7acf72af4b12db37fdb18;
+ 67cb9fc2712a199e533fa915
+ ""
+ ""
+ ""
+ ""
+ dbe0886648906617f156b7749baf20d2;
+ 6308cdec3f768281e040a9b9
+ a2
+ ""
+ ""
+ ""
+ d250af0db768e3345e8cb717015d4481;
+ 22bd689aef66f5306ceb0c6b
+ ""
+ 08
+ ""
+ ""
+ 11cea01fc59f767221b1d1f2d0143b96;
+ ac8b0a22260c571b4a42bb8f
+ ""
+ ""
+ db
+ 51
+ 2d05a8a0ba680cee9cd48e338c8b48a9;
+ 233bfa6a5cfb0bad7d95214a
+ de49cb3b6f5fe8368131115c037ba323
+ fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c46f88de9fd41e72d7b97e23e6
+ eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d7100b8b649377d20a8f08345
+ 0499046ea761b7f3aa662f3bde9f5f0c37f36bb3fb0d364b585c4d2b0e4f4a66153fba1b366ac0c79439aeca1967adb8
+ 8d5c3aac36d523729b5afb91924ee629;
+ 5b663e4ee1315f3c8f2aebfa
+ 921451dcd1af5813b70d30ce
+ 2f1fef6ef315d0798391805da08da3aefc5f85
+ 84b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684
+ ef0a5118e770a0a6ab603d85ad16ffecfc3e84c9c4e6390c6a658ba226d4f85ed42d57e886a1076bdd9ffae334371a545add74a74a6e59c7fb
+ 79064ad707bf5bb9f2443064d63635af;
+ b5aefa69a4cd52147ed12ca9
+ 86981a874498ad0abef8bc4fcb70e2
+ 7e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720ee
+ f9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d8
+ 83eadff65bdc0a99b0c11b2414491643ef798658f9a4a2c78a46c89ca7476745450aaa0add25c28bd3c0eefeac9e7f19f3d95904d0
+ 10317aaa71d95a323784406eecfc6621;
+ 58cbbc8424d126b8
+ ""
+ ""
+ ""
+ ""
+ 4108dabb7754ccdf2f498097fe2493bb;
+ 07e6daa089c3f909
+ 9c
+ ""
+ ""
+ ""
+ d2b1658dfe8f7e211bf9f3bee32064a8;
+ 5ffb824173d7634c
+ ""
+ 04
+ ""
+ ""
+ ab2e2975c1c3b9bc07bb7b2c7a3f55fc;
+ 226f30cbb7f0e4a9
+ ""
+ ""
+ 73
+ 51
+ 104b6be42e4ebbd2b94e5da48806507a;
+ a8cd190107314717
+ a77456f3ff669c732b58db8f48af65f7
+ cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0cae9ce021a5f1fa4ffa91
+ 544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967c0a458cb948bdd
+ 8b86c6c7e623c9e343ae7b1fa3d1eb8d38263234e881594a86fa291136d838ea2326aab6f331ed8241dc5632ab3dd10a
+ b0a96f29b83f2b02056bf2e94ac43147;
+ 409b687fa3a6827b
+ 480aa3a4c84cef64f6c9b53b
+ f8f957f4b03cf43e89957f9a3e8128f8743d16
+ 687b7bb8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac8451399587011677508a15dde524af3e2bee0646541a42c2eccc
+ 96544d398a17314d02e7345a80062864904f86b8ba0280f29064775fb7669b6b2fc8f7e9b1fa6a213ec25349802826b9a6148ef2954df0a019
+ c7a2ce4d1d3d9949eabebe7a572a5f7c;
+ b44d65bad397abfa
+ f529ee41cf9a05c7efedef3401539c
+ 51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a5718fd25014107c8e7d715a92add9589d1f5c0
+ 54b2d983514605ec590294a319b9802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70d17d4569eaff59a332ba58d5d5589bfe
+ ed9ebcc7d472e5707c7102b1cf72f2330419fbc2162a8d603f0bca3963eaf35992339cbe19b1525909be51f7a4cfebcb0b20efb5e7
+ 11a34ad52fc2412ffde804945f7527de;
+ 079753ee1a957eb6d6699e6b7ea2725cb2
+ ""
+ ""
+ ""
+ ""
+ bfce79cd62f6cd0cd7bb988245358c97;
+ dac07ecde95759ac46fee6dda7abc8ad68
+ da
+ ""
+ ""
+ ""
+ 1582dba1ba23714f141583436dbb0af1;
+ ac90cfe22d2f1f2968cc42fa8b669ed3bb
+ ""
+ 35
+ ""
+ ""
+ 7e202b58482cc68bee3ad6f7ccd6c034;
+ 42a9cf44bbc8c6254d980398bd94e66eb4
+ ""
+ ""
+ 56
+ 19
+ e5560f7f46d1747af91a51b39fa2a553;
+ 3d405e51881e99027b8ab9aea3ccf860b0
+ 009740763d96836c5f87b95460938de1
+ 288c69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c3680
+ 0d9645563a308ba60076817523bd2abf1261b089d8f23a9c2835076a23faac2cdd67771cc667a8331f0a170b66283e4f
+ a86b53285f02553f8eea5475249f7d19cdd539a0a2544e883ae030bdab6c626b5a459a384171205e95534a8e5c6658e1
+ 6fca68ddf9bfb6b8a06b44be4bb55eec;
+ 834a06148f302c3973accd56f6f24e3395
+ 8b8c2e2352fd61e4fa8fec81
+ 6ac861a8b33779f09e7a10fc02a8f48afa3080
+ ee119a52a9a817e4f2b94b0820cab383a8cffeea7c486315799dc875fba578c8ec4837898a92142b5b0677da1ac273117b45bcfff5d5f8b6fd
+ 25c9ca2752529fa0759c758d42f753af1a4ab5b3f036d585663ce2c886009a979951f8ea9e492a2175238be31f71aecb2a240e14be8873994e
+ 944a53fbe54197cb27d46c0f768fde88;
+ e2893232a9f81d14517ffae475f6b94a43
+ a67b3d380d2f9aaafe2dd721c0095c
+ 8808847689211450ba8095ffab1eaadf66fd22ac1976063e113ab61f813e28a1397a7974a1d7f4220c785f
+ e426a5a0e80f678d404147842941feeffdc2eb44dc8c0d5e8f444f7f4e0c893959b74dc23a7bb40e7e0013e5150686d2301b43a15a
+ 365bec4034b390949b707acfee0545eb79e0b47d87cdb901af6c3e964a997fe8c0faa678fa214c8ec5887e250c0d3007b2f1e29a93
+ 2fc6d2d214bcad3f502b9bf292029e1c;
+}
+
+twofish-ocb1 {
+ 60d7bcda163547d348b7551195
+ e77022907dd1dff7dac5c9941d26d0c6
+ ""
+ ""
+ ""
+ 8d1cfee1984c2e05a4a9b88de25d0b03;
+ eb14ad568f86edd1dc9268eeee
+ 533285a6ed810c9b689daaa9060d2d4b
+ 60
+ ""
+ ""
+ 71a0344b8fa6bcb38a5dcd91fe1ea7f4;
+ 03062365b0a54364c76c160f11
+ 896c4794846ecfa14a7130c9f1371206
+ ""
+ 34
+ 79
+ 7ad05aa4fccea98135597fed29e12041;
+ c9519848a877ff77bf79192a5b
+ 50ade5d9cd739a3d1f337f29549e6b0d
+ ""
+ 27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a21635c6d62c9269029df3e
+ bd4d3d7b5c177d602a76b0d30f94b746925a97ac08dbed466c21f623133b3b4a07a0cb3122bb409131b91e4891b4ad23
+ 8184dd419c0d7f3c10ae44312fdf5223;
+ 6057acc87638f508046733d9ff
+ 61cdbda3b3e9878731ebfedd4705e505
+ da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb621b7f65b000961040ef2f9b2fc5f
+ a450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215abd6b3ad54
+ 90126eb72fa9923afc3d8381c787206cc21e1c0310b3aed18859d30dcccbebf00a040d6dc4127e8993eabc5d302aea03
+ 2b753135ff0238a472730691c382446b;
+ efc9a38378c5b93bf4f2aad260
+ 5faee2b03fb648e27fff63102758fe2b
+ ""
+ 69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219bfb474fd71d891f24bb65d1563259f9e
+ 261413d3a72447a6d5ffce0583f1b4af32e7203b82f5d6e8686ab8c21873e4741a9dff70ab872edffdbe7a795a7b4b7f469f3a6de5
+ eb7184fda3922f373e8bcd6ca37d4042;
+ b53b571ea629c54d57dd2d42f7
+ 0800df9fcbaca48b77dba189196d1ebb
+ a10b0467cb9fc2712a199e533fa9156308cdec3f768281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b
+ 0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da67
+ c7a8156ec4894b7015e422efd4f9030c74e9e217ff1f15c02897a105a5c154391dac634298996cc30a8b383964cee203325787172e
+ 646143dc04f96fe66f7b7e10e2d956c2;
+ 94c18b5337685a96ed65b9ac
+ a338527ef19b09c063c46f88de9fd41e
+ ""
+ ""
+ ""
+ 0298067ddb8e8ad3a35c06d9aaa23012;
+ 72d7b97e23e6eabdff3bcd21
+ 1499268878dbf30f1dad89d4b9b12012
+ e4
+ ""
+ ""
+ 26caf5aed4068af4fcdbf0aab49387c5;
+ 713df46795630e7952d22bb0
+ 2d7100b8b649377d20a8f083455b663e
+ ""
+ 4e
+ de
+ 147491a865a55479e7820b48d65cfe86;
+ e1315f3c8f2aebfa921451dc
+ d1af5813b70d30ce2f1fef6ef315d079
+ ""
+ 8391805da08da3aefc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e303
+ a9ba8b1b3a7f68575146960578aaec63e43366c7ae57e481739749d32bddde3c33c7b4c5e096c8c0a96e2cbf5adecd17
+ 0eab7b499f15026215627b43e0b9c17a;
+ 08be3c31e6bc58c0b7cadcb6
+ 58b970e47479a684b5aefa69a4cd5214
+ 7ed12ca986981a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9
+ f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0cfa9138ddc39908
+ 0dee60335c90fde30d3e167df72c778839a69219947fcafa74f9bc6c21e32904b4298c20484c010e3aee5a032e33d3c9
+ 9a199af39e93cb1225d112e9c0f01d61;
+ 445608fe95e81c2533e31c9c
+ 1a9851bc2810d858cbbc8424d126b807
+ ""
+ e6daa089c3f9099c5ffb824173d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db8f48af65f7cc9e3f
+ e2a3d6365b19a3761fd7be55731c5b3dbce322f528a322b8c5b24453cb6a22656c944a6e304f5b3fb4b7cffdd5f87e17fe54664f5e
+ 8af45bd468a49b9fb4af7dee23301b73;
+ b90e1721b730374ffc9bc597
+ f56ccbb2f294b38766fc69f6a9f2c094
+ 5ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff6
+ 778554acf1270485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f
+ 9736fd0b0e9860bfb50e7d81301a7cec617bb1783e531a6708db5c790c5ffc287ce2e0f79d9a763bfff28182787061828fc2ed02fc
+ a00c4e76ab4c35fd8801455c627d2b9a;
+ 9a3e8128f8743d16
+ 687b7bb8deb9bd205b70e04c091d205c
+ ""
+ ""
+ ""
+ 5f6ea6b0475400a164944c4a31a7547f;
+ dad9e9a79b1abf91
+ b0851e5ca605ac845139958701167750
+ 8a
+ ""
+ ""
+ e55c85fb82289b89250fd9f463b50b74;
+ 15dde524af3e2bee
+ 0646541a42c2ecccb44d65bad397abfa
+ ""
+ f5
+ 98
+ 82d904459d8811b4f0907618d0215d93;
+ 29ee41cf9a05c7ef
+ edef3401539c51d2a90bbf7f1bfc338a
+ ""
+ b0ef5746ea8fdcccd213e33f7e8a5718fd25014107c8e7d715a92add9589d1f5c054b2d983514605ec590294a319b980
+ ff802a1e6113b0aac88c7a76f0338e3c95fc70c98801be1476af39a21b8bc15f5cfdf6c5643a716ab23091a187014eb2
+ 3b80083b38ba73e4d4bab2799e93b59b;
+ 2068a9f891bc5ba5
+ afabf8c3122d12d7ff3c41122d70d17d
+ 4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8ad68
+ daac90cfe22d2f1f2968cc42fa8b669ed3bb3542a9cf44bbc8c6254d980398bd94e66eb4563d405e51881e99027b8ab9
+ e0d20e66b71e3a13aedd139a71c5823d4fbee0d3a59e3c6414b562999b2948ee764542cfa3e846d92d2afc1f4374034d
+ 379db2c942b5aae433f382256bec565e;
+ aea3ccf860b00097
+ 40763d96836c5f87b95460938de1288c
+ ""
+ 69d80ea12ff4bb5f069b8a2e86041c1b9fc214e9ca2186ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c36800d9645563a308b
+ be3aa26f73e11ecc3bc58559bcdb8b6e1fa772bf51cddfbcf1bda58fa77945b735ede1d04f1b0b3d9b732ce7852082e8ed98b9e63c
+ f5d209e5468ccc2e7988a33924daf18f;
+ a60076817523bd2a
+ bf1261b089d8f23a9c2835076a23faac
+ 2cdd67771cc667a8331f0a170b66283e4f834a06148f302c3973accd56f6f24e33958b8c2e2352fd61e4fa
+ 8fec816ac861a8b33779f09e7a10fc02a8f48afa3080ee119a52a9a817e4f2b94b0820cab383a8cffeea7c486315799dc875fba578
+ 4bfc4201c557734332bd6162fcc0527136cd4ba9b3ea9dd265a3901551abc061862e1e1643a6fa6ae23cfce273204557d56e9e05ca
+ 8c085a22b651c7c3e54710d958570722;
+ c8ec4837898a92142b5b0677da1ac27311
+ 7b45bcfff5d5f8b6fde2893232a9f81d
+ ""
+ ""
+ ""
+ cc01d47fcdd2ebfd7fc167351b89c25c;
+ 14517ffae475f6b94a43a67b3d380d2f9a
+ aafe2dd721c0095c8808847689211450
+ ba
+ ""
+ ""
+ b604e266d82e05f040dfa3e55dca1544;
+ 8095ffab1eaadf66fd22ac1976063e113a
+ b61f813e28a1397a7974a1d7f4220c78
+ ""
+ 5f
+ 68
+ 87c774626abd1daca5cddd7c8dcba032;
+ e426a5a0e80f678d404147842941feeffd
+ c2eb44dc8c0d5e8f444f7f4e0c893959
+ ""
+ b74dc23a7bb40e7e0013e5150686d2301b43a15a84e81d7f5cedaa49e2414ebf47970e560475cff206877de69146acc3
+ 1f0dfa5f0c07208cf7d6e19d3b49c4335b63416bdf67eb3667d2642bcf8d8639f03c58ab865cce0f068b222eac1b3ad8
+ f580549f5cce1fae5e1df61bfd49c97a;
+ ab6cf8556b7aa776945948d1b8834df219
+ 6c92ec1718dcdeee0d52d9539726d281
+ 0391b3f9d10c39b07ae8f08ce7cee4758a386a9943e97dedfbe61e737882cd09c2b9a80f34c0fde11c2481b11fc76bfa
+ 4dbf710a9e544e0c536ca1e040f9ad5b04140d98edabe08485290a4d87d13b07398a1458c2c6b61dbdbc1cccada8c1a0
+ 0efa3388b0f1344526b97696cd61d5974dd9339a37fdfd020ef6687384208deb99fb2c79a91bfcf57135ad36f60aeabd
+ 12c3060b6d5cd360d29a9f8ee62bb1cb;
+ a9aabb6c4e3c3554f8fb1ef61614c27029
+ 5dfc0ca6551ca4bdb75359f91cb9d921
+ ""
+ 056b7de74fc9a9b37154ce6c0b396179d31f06a1dd5982cbc0d7cb23841da1ae8f4ae480cda98ad6cf2bacf6f9fd3f821330c43f3d
+ e2c8468063ab076373bf2c088a0a7a9acc80937ac2f29036a733b089f5214311bf48de59cca31051ad6eeca19f34154412d3e4acbb
+ 887f83fd9a8db0d28cd849e7ec0cd72d;
+ f6c2b3fac7cbcf96523d4723f91801325e
+ b8553236651c96788d73d192ee53b3f3
+ ebd66ddd98cedbe88e245de25b1593b70f8601562d90a9b59ed034a867642d25d54756fa5c47f16f64b837
+ bb4926214211a1c696ba172010abb433922a22d9fd881519165eb9d85197a21cc34ac0d5ae7be8dbf98e4ffed2cf6b1372a5aa47b5
+ 6ce7de9f52ff4f4fc21a63423b6d084752f7f7dc7b4e2c7d781a7fc6c468d2ad5a694156b41e8033ef66a59606919b13435453b037
+ ef0d9a53c0eadbb12806aab80d24d67d;
+}
+
+twofish-pmac1 {
+ 60d7bcda163547d348b7551195
+ ""
+ b9898ea028d9c1fb8192e585467aeff7;
+ e77022907dd1dff7dac5c9941d
+ 26
+ d2547a3fa161edf4427ac2523c0e12f4;
+ d0c6eb14ad568f86edd1dc9268
+ eeee533285a6ed810c9b689daaa9060d2d4b6003062365b0a54364c76c160f11896c4794846ecfa14a7130c9f1371206
+ 629a79b85d3c132fa98b11bd247ae22a;
+ 34c9519848a877ff77bf79192a
+ 5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd8
+ 78a88c6c5a799d4bf7276ef82681502b;
+ 8374d8cde8e160ad10997a21
+ ""
+ 142ab85c8da67eb03c02351267ac528f;
+ 635c6d62c9269029df3e6057
+ ac
+ 97ef82a6ab463b32b3c6de3b8858e703;
+ c87638f508046733d9ff61cd
+ bda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb6
+ 13e0efe3390a5696584ff6f095c9d866;
+ 21b7f65b000961040ef2f9b2
+ fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c5
+ 550b74f7ec72626368a2c58ce23bb008;
+ 4215abd6b3ad54ef
+ ""
+ f5dd9becdd3d3fbecc3dee067bb06ff6;
+ c9a38378c5b93bf4
+ f2
+ 51c108d4abf0343491d7ec7b74e35736;
+ aad2605faee2b03f
+ b648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219
+ 1939152c1f82c19cc084a681ccdfbd3e;
+ bfb474fd71d891f2
+ 4bb65d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9f
+ cdd10d315afef9594ea2d5be06e2e839;
+ c2712a199e533fa9156308cdec3f768281
+ ""
+ ba9d8b182c751b42b9796bae5985d048;
+ e040a9b9a222bd689aef66f5306ceb0c6b
+ 08
+ b504bad203181c0281e60284b1e93cd3;
+ ac8b0a22260c571b4a42bb8fdb233bfa6a
+ 5cfb0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b5337685a96ed65
+ a23f906ae8ec8b99ff2344d2f22c953c;
+ b9aca338527ef19b09c063c46f88de9fd4
+ 1e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012e4713df46795630e7952d22bb02d
+ e8dc0b7392f193529199018bd6939012;
+}
+
+twofish-ocb3 {
+ 60d7bcda163547d348b7551195
+ e77022907dd1dff7dac5c9941d26
+ ""
+ ""
+ ""
+ 7f2677b3ee050809f5e4a511a007024d;
+ d0c6eb14ad568f86edd1dc9268
+ eeee533285a6ed810c9b689daaa9
+ 06
+ ""
+ ""
+ be8deddf16817c9c36d0fd7a1bfbee5e;
+ 0d2d4b6003062365b0a54364c7
+ 6c160f11896c4794846ecfa14a71
+ ""
+ 30
+ c0
+ 08ab7139235abe4995e765e6a3cb82a8;
+ c9f137120634c9519848a877ff
+ 77bf79192a5b50ade5d9cd
+ ""
+ 739a3d1f337f29549e6b0d27a4ba234085406a6136512061f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a
+ 47e1cc7b95ebd79869a91c2f062b8f2f577d56908f819cd78f55430e51223e2a5e37bac236601388a2b434c26aa8e7d2
+ 5507241b459462d018dae1537cb30e8f;
+ 21635c6d62c9269029df3e6057
+ acc87638f508046733d9ff61cd
+ bda3b3e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb6
+ 21b7f65b000961040ef2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a480
+ 7f7357f93fcbabb0d2900992381ab4c3ace2bb992327a4d3d62ff63756b7ef734a0c2a6de3c4b01f76c3531ddd58edcf
+ 947dd27aa266be2c3d043571d4a14bb8;
+ 30370c33d090c54215abd6b3ad
+ 54efc9a38378c5b93bf4f2aad260
+ ""
+ 5faee2b03fb648e27fff63102758fe2b69ac26afa3349829b94586306fed54154f8f28523c03d4de1600157846b710ee72807a2219
+ baaa3ba12dcb88379960d13a294e16ae35fc238cca7e1ebd514ef33d2581ffff81c2860478a0ac7be7e2aec8b16ea37fe9e7df6f40
+ b106b18872d92b55b10125092c07ca8a;
+ bfb474fd71d891f24bb65d1563
+ 259f9eb53b571ea629c54d57dd2d
+ 42f70800df9fcbaca48b77dba189196d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f768281e040
+ a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b6f5fe8368131115c
+ 3c67bd32c69ef6446bcf3b1ede303d6bc287368abaa84bbb26ead3899423d3099eca75c966044b67bafb88404ad639fae5857f3a6d
+ fc24dd4b1e6fdad71a59b7595a9e776e;
+ 037ba323fe1dc8151784873f
+ 0eb5b647da6794c18b5337685a96
+ ""
+ ""
+ ""
+ 8b63ff209b6e7a0391301e76a4e0ea39;
+ ed65b9aca338527ef19b09c0
+ 63c46f88de9fd41e72d7b97e23e6
+ ea
+ ""
+ ""
+ a433659f0885976882831a3eb89eed53;
+ bdff3bcd211499268878dbf3
+ 0f1dad89d4b9b12012e4713df467
+ ""
+ 95
+ 6d
+ 42fe65d65b86c7528a73f89a0ccdf4de;
+ 630e7952d22bb02d7100b8b6
+ 49377d20a8f083455b663e
+ ""
+ 4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f
+ 674e1ecd1a10232c74655502be244c4fb08e1f727cb9131f2d2e46de210815b286fc3a75d4e3e1d50c82aa1453b3ca08
+ fa220b12d50ce64f83a4884807d53c83;
+ 16e39815d4e9cfce3ed1ecdf
+ 3d264a7f16cb16c2e815f422cd
+ f0c8e30308be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a874498ad0abef8bc4f
+ cb70e27e98ef1f0446b42fb144d44b6d00f06dc188d472a784e0c6f21195a3b9f4ae985511265febd11c164720eef9eb
+ 8b26c53a06f4ce39b4f35da14098aa964a66b58d9d3385ac71fc9a4f31a6d2c69bd41780ef50785b2d4dc3c8d8de5ec3
+ cb0b3d4ebe62634b66cb4c2f07a22bb8;
+ 1c8dd0b00951f284649016ed
+ 00456331854bc78bf43966eb0cfa
+ ""
+ 9138ddc39908445608fe95e81c2533e31c9c1a9851bc2810d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f
+ 45a59590b5218d7503eac38def06f24dde786aee5d74aa5818501d881b5955b3404fc92c02e671c95f03b6e10c875e43309e6314d8
+ cc019326324d5f7a3ccfbf7fb4b4d007;
+ 30cbb7f0e4a973a8cd190107
+ 314717a77456f3ff669c732b58db
+ 8f48af65f7cc9e3fb90e1721b730374ffc9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003cc0c
+ ae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65cc1770a18cbfe6effd1ff6778554acf1270485b203a3c1c4c967c0a4
+ 601106b9872e22a419d22e77179a9d3f2f49259f77629473d6fe8cca0c7f80e94230ebb6c59aeaf544a26537b633cf3faca9afaba8
+ 3eb85702ecc6a6208ff54e70c555d560;
+ 58cb948bdd409b68
+ 7fa3a6827b480aa3a4c84cef64f6
+ ""
+ ""
+ ""
+ 536ee06e4186eb19069cc7d2611bf1da;
+ c9b53bf8f957f4b0
+ 3cf43e89957f9a3e8128f8743d16
+ 68
+ ""
+ ""
+ 7eb7549c58f0b3e0e900694ad60a34f2;
+ 7b7bb8deb9bd205b
+ 70e04c091d205cdad9e9a79b1abf
+ ""
+ 91
+ a3
+ c223c24ae40f10208b2d07032bf63b9c;
+ b0851e5ca605ac84
+ 51399587011677508a15dd
+ ""
+ e524af3e2bee0646541a42c2ecccb44d65bad397abfaf529ee41cf9a05c7efedef3401539c51d2a90bbf7f1bfc338ab0
+ 54484aa14a10c80f224295d4fdc98a962cb1a75c388282477149c9e2ad42cb7e19f72d20ecc895ffcdd94e5e184d4195
+ 7790694ff014f4f29d8875d3483c665d;
+ ef5746ea8fdcccd2
+ 13e33f7e8a5718fd25014107c8
+ e7d715a92add9589d1f5c054b2d983514605ec590294a319b9802068a9f891bc5ba5afabf8c3122d12d7ff3c41122d70
+ d17d4569eaff59a332ba58d5d5589bfe079753ee1a957eb6d6699e6b7ea2725cb2dac07ecde95759ac46fee6dda7abc8
+ 873b418fb6d2d8038dd78169b110a57f6e6c58d917f938d27bf4cdb6a9a3e64b6782c71fa8001c22b4025ca054cdc7d4
+ 80b7822cbc9921b5249460298edc38b0;
+ ad68daac90cfe22d
+ 2f1f2968cc42fa8b669ed3bb3542
+ ""
+ a9cf44bbc8c6254d980398bd94e66eb4563d405e51881e99027b8ab9aea3ccf860b0009740763d96836c5f87b95460938de1288c69
+ 0be9726d678b4975083f0553c995e8fe2e9397ae7b1099320daeff9b57e43d306f05d8806cda76754bde21c5aa5a038b2ecd64eff2
+ 5fb04d39cbaf88ea62135df4d4661bf0;
+ d80ea12ff4bb5f06
+ 9b8a2e86041c1b9fc214e9ca2186
+ ddf1f6a7a3aa7e740da967828e3604b35b15ffaa6c36800d9645563a308ba60076817523bd2abf1261b089
+ d8f23a9c2835076a23faac2cdd67771cc667a8331f0a170b66283e4f834a06148f302c3973accd56f6f24e33958b8c2e2352fd61e4
+ dfbe4cf0fe2983dc101e9daf7d40770c0e6f679e56fe4947602c739ebf22782fb98932e02eb14973d825ea72fb651b6eafca5232ba
+ f92fdadf740caf2c4ea9666b7b052af2;
+ fa8fec816ac861a8b33779f09e7a10fc02
+ a8f48afa3080ee119a52a9a817e4
+ ""
+ ""
+ ""
+ 94c3b0151d59ed8a75ce295b97ca07f1;
+ f2b94b0820cab383a8cffeea7c48631579
+ 9dc875fba578c8ec4837898a9214
+ 2b
+ ""
+ ""
+ c88555532a51ef0d2999fd4b5964866b;
+ 5b0677da1ac273117b45bcfff5d5f8b6fd
+ e2893232a9f81d14517ffae475f6
+ ""
+ b9
+ bb
+ 2b2e9ebf26398af33b06cae0b1edf872;
+ 4a43a67b3d380d2f9aaafe2dd721c0095c
+ 8808847689211450ba8095
+ ""
+ ffab1eaadf66fd22ac1976063e113ab61f813e28a1397a7974a1d7f4220c785fe426a5a0e80f678d404147842941feef
+ aa8ff926ae1d31b79b276ba4c6365896a9ac3f2b901cc6edbd98ef230dcb0c1175fc4cda3d3bab4b0cd0761ec60d1bf9
+ 679ea4952bdb67410905826ee2164b91;
+ fdc2eb44dc8c0d5e8f444f7f4e0c893959
+ b74dc23a7bb40e7e0013e51506
+ 86d2301b43a15a84e81d7f5cedaa49e2414ebf47970e560475cff206877de69146acc3ab6cf8556b7aa776945948d1b8
+ 834df2196c92ec1718dcdeee0d52d9539726d2810391b3f9d10c39b07ae8f08ce7cee4758a386a9943e97dedfbe61e73
+ 5e3f9325ceafcf8ab3c05194722e13093f75502a722f012fcf67c3f78d905711e90f6f8b2cf11e4911fcf8a988c95fd9
+ 715a5d5c308eb6c2d35c87de8c9bc36d;
+ 7882cd09c2b9a80f34c0fde11c2481b11f
+ c76bfa4dbf710a9e544e0c536ca1
+ ""
+ e040f9ad5b04140d98edabe08485290a4d87d13b07398a1458c2c6b61dbdbc1cccada8c1a0a9aabb6c4e3c3554f8fb1ef61614c270
+ f0849293c90d1b433a612900ab035a2359b4b0f40dae24c375d721449707bd4fbec89c934fc1610231b4171407dddf5d1cd26e4588
+ e8b6889f97e92f7f90bd3367a6509d3c;
+ 295dfc0ca6551ca4bdb75359f91cb9d921
+ 056b7de74fc9a9b37154ce6c0b39
+ 6179d31f06a1dd5982cbc0d7cb23841da1ae8f4ae480cda98ad6cf2bacf6f9fd3f821330c43f3df6c2b3fa
+ c7cbcf96523d4723f91801325eb8553236651c96788d73d192ee53b3f3ebd66ddd98cedbe88e245de25b1593b70f8601562d90a9b5
+ b1f9684caf6b151fdfcf38fcc9280ba779c2c5845bf3f3778eec5d7157134dd51c762d40ede77e70255f24e7cde7fb41c4e87aef3e
+ ae37ce3b049000e9a941f2e36ffc1b98;
+}
+
+twofish-ocb3-mct {
+ 32 e9ce6449d92a77813175926010259b8e;
+ 28 a99db77f8c91ea244b94208509e02f0c;
+ 24 9a9b6ce8abdbf68c23f2ad13d9e46119;
+ 20 c8ef353c81e5742726a0128dd0a0f588;
+ 16 9c839aab8a36976e9d320767766e0aa6;
+ 12 7f3551b1eb590266c7d59ec6b2b14aa8;
+ 10 15fd08dea6427de5fb88050905d313b5;
+ 8 3615f256e0edc05af17b680d13534820;
+ 4 5a7c50c4e1263d509f2a263ed3587b2d;
+ 32 fbe280898f5232dfb0abd143;
+ 28 0816b9db96448972f47cc0b0;
+ 24 1fdbf8b9482aa91ef2975556;
+ 20 3292677aa668b89b179fc183;
+ 16 f1f605105a477669efdd0426;
+ 12 aa1d9537f7ae2c5c1729c147;
+ 10 e9b833d9ff3c9fc07b037282;
+ 8 138e0305a1520249dd678e0d;
+ 4 ebe50e379a1973275bca0d3d;
+ 32 0a09c938c2fa5dba;
+ 28 3e38764a044b24fb;
+ 24 fe6aa4380d1b161e;
+ 20 0e065914f197a226;
+ 16 31747d608f91f1a7;
+ 12 ffc71de4b3eec92d;
+ 10 fbe711df96a56989;
+ 8 b38b5c7577aea195;
+ 4 9530ea1063f27742;
+}
c86c21d8c26dc291f662c8f2fe79b74b 0993d3b68c1d4a5d 2b4195c3d67e3f99;
af4f4615c7c298639b9728251991419f 1e268f9e710313b5 2536ccd8fdfe30e1;
}
+
+xtea-cmac {
+ 60d7bcda163547d348b7551195
+ ""
+ 3fe52353f9b144ae;
+ e77022907dd1dff7dac5c9941d
+ 26
+ 809e38cc35e3a145;
+ d0c6eb14ad568f86edd1dc9268
+ eeee533285a6ed810c9b689daaa9060d2d4b6003062365b0
+ 9e781632642b42cd;
+ a54364c76c160f11896c479484
+ 6ecfa14a7130c9f137120634c9519848a877ff
+ 8d187ce6f32516ae;
+ 77bf79192a5b50
+ ""
+ 12bacc0346a97c7f;
+ ade5d9cd739a3d
+ 1f
+ 76efca6f4ea48f3a;
+ 337f29549e6b0d
+ 27a4ba234085406a6136512061f7080cc07df0591d8fa21f
+ 390ba4bcc9d100f3;
+ 2dd88374d8cde8
+ e160ad10997a21635c6d62c9269029df3e6057
+ 666111e472d8cdfd;
+ acc87638f508046733d9
+ ""
+ 2b1ff3b380aa5d5a;
+ ff61cdbda3b3e9878731
+ eb
+ 85351b61c26c94cf;
+ fedd4705e505da1435dc
+ eaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533
+ d8a892f0975b7e2c;
+ 966f27043eb621b7f65b
+ 000961040ef2f9b2fc5fa450727a9b542cde52
+ 85b42005a520b9fc;
+ ebfda19d0ccc520f21
+ ""
+ cf0f227f8b2a8b46;
+ 5eb57bb3a4f3ebbbb1
+ 8a
+ a0cdc4acc3d77c92;
+ c6c95a97a48030370c
+ 33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad260
+ ac879bd822cf405d;
+ 5faee2b03fb648e27f
+ ff63102758fe2b69ac26afa3349829b9458630
+ 295b9c45cd0a8bab;
+}
+
+xtea-ccm {
+ 60d7bcda163547d348b7551195
+ e77022
+ ""
+ ""
+ ""
+ 254c9820;
+ 907dd1dff7dac5c9941d26d0c6
+ eb14ad
+ 56
+ ""
+ ""
+ 628ee141;
+ 8f86edd1dc9268eeee533285a6
+ ed810c
+ ""
+ 9b
+ b6
+ c68f9ba1;
+ 689daaa9060d2d4b6003062365
+ b0a54364c7
+ 6c160f11896c4794846ecfa14a7130c9f137120634c95198
+ 48a877ff77bf79192a5b50ade5d9cd739a3d1f337f29549e
+ 5d451b7841e1046387c69f33e87585eedf30cd7df2d4a409
+ ae1ade48fb30df53;
+ 6b0d27a4ba234085406a613651
+ 2061f7080c
+ c07df0591d8fa21f2dd88374d8cde8e160ad10
+ 997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbd
+ 587e64a45665ec8f4b0561f911c55bbddc89d3cb923ee2a79736d853f2
+ 5dc68eee0336d9df;
+ a3b3e9878731eb
+ fedd47
+ ""
+ ""
+ ""
+ e731a2e4;
+ 05e505da1435dc
+ eaa7b1
+ cc
+ ""
+ ""
+ d61b3844;
+ 49ae1d50c38201
+ a89447
+ ""
+ 6b
+ 65
+ ae5cf49a;
+ 3f102b752eb952
+ 9533966f27
+ 043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542c
+ de52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a
+ 5cda052e11d440e05347a5d392610573bb3382f451a23c91
+ 6b984d2bbcde1308;
+ 97a48030370c33
+ d090c54215
+ abd6b3ad54efc9a38378c5b93bf4f2aad2605f
+ aee2b03fb648e27fff63102758fe2b69ac26afa3349829b94586306fed
+ e50f8051933dfcda7693161d2fa0885f455a610c3178d245abb8a7869c
+ 9bba96ded767f109;
+ 54154f8f28523c03d4de
+ 160015
+ ""
+ ""
+ ""
+ 06d07295;
+ 7846b710ee72807a2219
+ bfb474
+ fd
+ ""
+ ""
+ 613f97d3;
+ 71d891f24bb65d156325
+ 9f9eb5
+ ""
+ 3b
+ 10
+ 5262f065;
+ 571ea629c54d57dd2d42
+ f70800df9f
+ cbaca48b77dba189196d1ebba10b0467cb9fc2712a199e53
+ 3fa9156308cdec3f768281e040a9b9a222bd689aef66f530
+ 728d0e2c1f92403c6c91538ca0a4d33c644728aa324d6fec
+ 3c8af92993cf2dfc;
+ 6ceb0c6b08ac8b0a2226
+ 0c571b4a42
+ bb8fdb233bfa6a5cfb0bad7d95214ade49cb3b
+ 6f5fe8368131115c037ba323fe1dc8151784873f0eb5b647da6794c18b
+ 758c2450b1b4b633088e2dacece8fce73bb681518bc74f24427f9cf532
+ 768cfa0b76676f6e;
+ 5337685a96ed65b9ac
+ a33852
+ ""
+ ""
+ ""
+ cd3b5fbe;
+ 7ef19b09c063c46f88
+ de9fd4
+ 1e
+ ""
+ ""
+ 77ec39fe;
+ 72d7b97e23e6eabdff
+ 3bcd21
+ ""
+ 14
+ 2b
+ 12bba0f1;
+ 99268878dbf30f1dad
+ 89d4b9b120
+ 12e4713df46795630e7952d22bb02d7100b8b649377d20a8
+ f083455b663e4ee1315f3c8f2aebfa921451dcd1af5813b7
+ 84148214729971a1616f5a0a2261662e90ffe6ee853fc892
+ cd1f0f55d1d79d35;
+ 0d30ce2f1fef6ef315
+ d079839180
+ 5da08da3aefc5f8584b7c5e617669c0f16e398
+ 15d4e9cfce3ed1ecdf3d264a7f16cb16c2e815f422cdf0c8e30308be3c
+ fc533246fa0f63332c3806595c6a35a6cd0499e973ae7a0055755b4026
+ ff6e5bc754f0adfd;
+}
+
+xtea-eax {
+ 60d7bcda163547d348b7551195
+ ""
+ ""
+ ""
+ ""
+ 5f1c8be04844ffdf;
+ e77022907dd1dff7dac5c9941d
+ 26
+ ""
+ ""
+ ""
+ 3fec55f722a3295e;
+ d0c6eb14ad568f86edd1dc9268
+ ""
+ ee
+ ""
+ ""
+ 41b22cdc7a09818c;
+ ee533285a6ed810c9b689daaa9
+ ""
+ ""
+ 06
+ 68
+ 8b0dec6244e10dd9;
+ 0d2d4b6003062365b0a54364c7
+ 6c160f11896c4794
+ 846ecfa14a7130c9f137120634c9519848a877ff77bf7919
+ 2a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085
+ 4c3b648b0d6a0bf20eb496a17201e4fdd7581e1d34fe19f5
+ 9576894304df1c06;
+ 406a6136512061f7080cc07df0
+ 591d8fa21f2dd8
+ 8374d8cde8e160ad10997a21635c6d62c92690
+ 29df3e6057acc87638f508046733d9ff61cdbda3b3e9878731ebfedd47
+ 495ac874eee71cda95fc4133cd8080514898385e542f44f56734ff86cf
+ 88db0b0c36963625;
+ 05e505da1435dc
+ ""
+ ""
+ ""
+ ""
+ b8d2cf3b4a2c82ed;
+ eaa7b1cc49ae1d
+ 50
+ ""
+ ""
+ ""
+ ff304d08904cc45b;
+ c38201a894476b
+ ""
+ 3f
+ ""
+ ""
+ f13209350bfea66c;
+ 102b752eb95295
+ ""
+ ""
+ 33
+ 78
+ 468ff217fd2da0e0;
+ 966f27043eb621
+ b7f65b000961040e
+ f2f9b2fc5fa450727a9b542cde52ebfda19d0ccc520f215e
+ b57bb3a4f3ebbbb18ac6c95a97a48030370c33d090c54215
+ c78a890e811a86978a2b944c7741ce0fc415aba17675e5be
+ 835bb97626f8a99e;
+ abd6b3ad54efc9
+ a38378c5b93bf4
+ f2aad2605faee2b03fb648e27fff63102758fe
+ 2b69ac26afa3349829b94586306fed54154f8f28523c03d4de16001578
+ f8331f39c783a39406102bfdc1b324d0d4dabe5ec886474caef97209fd
+ e59ad9e764305aa4;
+ 46b710ee72807a2219bf
+ ""
+ ""
+ ""
+ ""
+ 603bc1df6ad3c9ef;
+ b474fd71d891f24bb65d
+ 15
+ ""
+ ""
+ ""
+ bd337ef6bfba87bb;
+ 63259f9eb53b571ea629
+ ""
+ c5
+ ""
+ ""
+ 155833e773266034;
+ 4d57dd2d42f70800df9f
+ ""
+ ""
+ cb
+ 43
+ d77a671a2285a75a;
+ aca48b77dba189196d1e
+ bba10b0467cb9fc2
+ 712a199e533fa9156308cdec3f768281e040a9b9a222bd68
+ 9aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb23
+ ba08278e81846ceb38153d309a3a01a57f415763091e31cd
+ 9ec9746c66fea592;
+ 3bfa6a5cfb0bad7d9521
+ 4ade49cb3b6f5f
+ e8368131115c037ba323fe1dc8151784873f0e
+ b5b647da6794c18b5337685a96ed65b9aca338527ef19b09c063c46f88
+ b73f49154f95bdba7d27565233290a8b987df10315aa519dd927f2c862
+ 8ebd3aa28ee4a127;
+ de9fd41e72d7b97e23
+ ""
+ ""
+ ""
+ ""
+ 6139eca5fd2a9750;
+ e6eabdff3bcd211499
+ 26
+ ""
+ ""
+ ""
+ 8acc9b1625d62fb2;
+ 8878dbf30f1dad89d4
+ ""
+ b9
+ ""
+ ""
+ 9730f31424a77b48;
+ b12012e4713df46795
+ ""
+ ""
+ 63
+ 33
+ 0db62109955eeea5;
+ 0e7952d22bb02d7100
+ b8b649377d20a8f0
+ 83455b663e4ee1315f3c8f2aebfa921451dcd1af5813b70d
+ 30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5
+ 67acf23790a2997df84bf037c61118541471b963e076eb73
+ b9d46f9d24d74df0;
+ e617669c0f16e39815
+ d4e9cfce3ed1ec
+ df3d264a7f16cb16c2e815f422cdf0c8e30308
+ be3c31e6bc58c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed1
+ 913b6bc765751a1b774bdd80b81b54a40e6b943acb8d922c5ea0b049d3
+ 32a223a2cb999dba;
+}
+
+xtea-gcm {
+ 60d7bcda163547d348b7551195
+ ""
+ ""
+ ""
+ ""
+ 965c89c5e9e67150;
+ e77022907dd1dff7dac5c9941d
+ 26
+ ""
+ ""
+ ""
+ 4bc1d47c6aa62964;
+ d0c6eb14ad568f86edd1dc9268
+ ""
+ ee
+ ""
+ ""
+ efbae174fcba078d;
+ ee533285a6ed810c9b689daaa9
+ ""
+ ""
+ 06
+ e8
+ 3c4fa10c897f0762;
+ 0d2d4b6003062365b0a54364c7
+ 6c160f11896c4794
+ 846ecfa14a7130c9f137120634c9519848a877ff77bf7919
+ 2a5b50ade5d9cd739a3d1f337f29549e6b0d27a4ba234085
+ bffee89ad704bd37259e148b3c038bf2ee483ee7e15cddd8
+ f679257dc029e7f1;
+ 406a6136512061f7080cc07df0
+ 591d8fa2
+ 1f2dd88374d8cde8e160ad
+ 10997a21635c6d62c9269029df3e6057acc87638f508046733d9ff61cdbda3b3e9
+ 77f4d28e0589a98ab60a4c53cf2a34a4212aee7756a9ebf17f5c52b982ae5dc249
+ d61642f2623b785f;
+ 878731ebfedd4705e505da1435
+ dceaa7b1cc49ae
+ 1d50c38201a894476b3f102b752eb952953396
+ 6f27043eb621b7f65b000961040ef2f9b2fc5fa450727a9b542cde52eb
+ f9d9ebb1b908d8d19893ce0bebb4c2b87110adc572425cf0d88b32fe2c
+ aa3002dffd42e3ff;
+ fda19d0ccc520f
+ ""
+ ""
+ ""
+ ""
+ dbafe92d502b3295;
+ 215eb57bb3a4f3
+ eb
+ ""
+ ""
+ ""
+ 09ac92680bc52ddf;
+ bbb18ac6c95a97
+ ""
+ a4
+ ""
+ ""
+ 2845ab8e15cc6e83;
+ 8030370c33d090
+ ""
+ ""
+ c5
+ 3e
+ 8b12bd215589da19;
+ 4215abd6b3ad54
+ efc9a38378c5b93b
+ f4f2aad2605faee2b03fb648e27fff63102758fe2b69ac26
+ afa3349829b94586306fed54154f8f28523c03d4de160015
+ 3dd971d21e1f273a18a156a12cc084d265744982a0bc84ee
+ e4bc1c22d869ce1f;
+ 7846b710ee7280
+ 7a2219bf
+ b474fd71d891f24bb65d15
+ 63259f9eb53b571ea629c54d57dd2d42f70800df9fcbaca48b77dba189196d1ebb
+ 35afbe16c12e4a71ee59d1e03479d82c240119d25d7f759298ca0c6a7261ec0df7
+ 0e3afa58d945282f;
+ a10b0467cb9fc2
+ 712a199e533fa9
+ 156308cdec3f768281e040a9b9a222bd689aef
+ 66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb233bfa6a5cfb0bad
+ 91c7d3e6bdfdc99a009642e8586acdb300caf64ccfa844f823b02fb3a3
+ 9d1d569032d47694;
+ 7d95214ade49cb3b6f5f
+ ""
+ ""
+ ""
+ ""
+ bf7b041a488d393e;
+ e8368131115c037ba323
+ fe
+ ""
+ ""
+ ""
+ 41f54145c986899b;
+ 1dc8151784873f0eb5b6
+ ""
+ 47
+ ""
+ ""
+ 46aa574328fd728c;
+ da6794c18b5337685a96
+ ""
+ ""
+ ed
+ fb
+ b2ae7fdba380ced8;
+ 65b9aca338527ef19b09
+ c063c46f88de9fd4
+ 1e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89
+ d4b9b12012e4713df46795630e7952d22bb02d7100b8b649
+ 9b3dd3969b6367d11a17e2c10241592ea531ecf0445749eb
+ ee022fa7e8e3a576;
+ 377d20a8f083455b663e
+ 4ee1315f
+ 3c8f2aebfa921451dcd1af
+ 5813b70d30ce2f1fef6ef315d0798391805da08da3aefc5f8584b7c5e617669c0f
+ 4d32b3228edff4d5a35588331c433defeca851b5843150082ac23d5607ea06c83e
+ d1458ac231a4ac20;
+ 16e39815d4e9cfce3ed1
+ ecdf3d264a7f16
+ cb16c2e815f422cdf0c8e30308be3c31e6bc58
+ c0b7cadcb658b970e47479a684b5aefa69a4cd52147ed12ca986981a87
+ 8603545fa254880d1fceb81d2e937217d0edfd7f6713078624772c0f40
+ fdc8cb8bc51a1533;
+ 4498ad0abef8bc4fcb
+ ""
+ ""
+ ""
+ ""
+ 9c3e0d53b5dca992;
+ 70e27e98ef1f0446b4
+ 2f
+ ""
+ ""
+ ""
+ 04bf8339880c70bd;
+ b144d44b6d00f06dc1
+ ""
+ 88
+ ""
+ ""
+ fefa3ef4a95dbe20;
+ d472a784e0c6f21195
+ ""
+ ""
+ a3
+ 6c
+ 05da912be7dd7846;
+ b9f4ae985511265feb
+ d11c164720eef9eb
+ 1c8dd0b00951f284649016ed00456331854bc78bf43966eb
+ 0cfa9138ddc39908445608fe95e81c2533e31c9c1a9851bc
+ e72acc6e0d4490e549b969d30f773905cd6dc77f4ce77b22
+ bb74ac6f9139c65f;
+ 2810d858cbbc8424d1
+ 26b807e6
+ daa089c3f9099c5ffb8241
+ 73d7634c04226f30cbb7f0e4a973a8cd190107314717a77456f3ff669c732b58db
+ 9e8854454d108c12f18f23fb9a251b52e734a3221aea99928614d209d6e57a4305
+ 44d67f8883a717e5;
+ 8f48af65f7cc9e3fb9
+ 0e1721b730374f
+ fc9bc597f56ccbb2f294b38766fc69f6a9f2c0
+ 945ffd505003cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f09
+ ae7ea2a80ef6b2ec3b48f32be277ce5f984f50af216261f69bc2e65c2c
+ db4d7130d6508aa8;
+}
+
+xtea-ocb1 {
+ 60d7bcda163547d348b7551195
+ e77022907dd1dff7
+ ""
+ ""
+ ""
+ 07bef2af9ee05be5;
+ dac5c9941d26d0c6eb14ad568f
+ 86edd1dc9268eeee
+ 53
+ ""
+ ""
+ f772f8da875c6c16;
+ 3285a6ed810c9b689daaa9060d
+ 2d4b6003062365b0
+ ""
+ a5
+ 09
+ ae03c614cee35738;
+ 4364c76c160f11896c4794846e
+ cfa14a7130c9f137
+ ""
+ 120634c9519848a877ff77bf79192a5b50ade5d9cd739a3d
+ 667c317875cb68a2df759151a2340d3b90c7652e0a4cfcb1
+ 93e92f0eef1160fb;
+ 1f337f29549e6b0d27a4ba2340
+ 85406a6136512061
+ f7080cc07df0591d8fa21f2dd88374d8cde8e160ad10997a
+ 21635c6d62c9269029df3e6057acc87638f508046733d9ff
+ 6f5d6a11b04cb03f734de83608675ca8cbb718197d5e6dae
+ e69dd7ec56052187;
+ 61cdbda3b3e9878731ebfedd47
+ 05e505da1435dcea
+ ""
+ a7b1cc49ae1d50c38201a894476b3f102b752eb9529533966f27043eb6
+ b2404d623b8994262e27a6e4e735dee18349a90f530e2a3f636d7c5f71
+ ef92c0c42a1911fb;
+ 21b7f65b000961040ef2f9b2fc
+ 5fa450727a9b542c
+ de52ebfda19d0ccc520f215eb57bb3a4f3ebbb
+ b18ac6c95a97a48030370c33d090c54215abd6b3ad54efc9a38378c5b9
+ b3c350ff78424273c10f103bbda2de658e037d6a35632be78052c55b53
+ 131383b16016457a;
+ 3bf4f2aad2605f
+ aee2b03fb648e27f
+ ""
+ ""
+ ""
+ 7080c42bba62492f;
+ ff63102758fe2b
+ 69ac26afa3349829
+ b9
+ ""
+ ""
+ a4e5b67ccd313289;
+ 4586306fed5415
+ 4f8f28523c03d4de
+ ""
+ 16
+ 00
+ d86ee5c4829dba67;
+ 00157846b710ee
+ 72807a2219bfb474
+ ""
+ fd71d891f24bb65d1563259f9eb53b571ea629c54d57dd2d
+ 5a963f2a946fc9b06c9c9949f50eb85c1f3b54e009ea3950
+ 43d5535e5b6fc923;
+ 42f70800df9fcb
+ aca48b77dba18919
+ 6d1ebba10b0467cb9fc2712a199e533fa9156308cdec3f76
+ 8281e040a9b9a222bd689aef66f5306ceb0c6b08ac8b0a22
+ fc5846409e369e01687535ae0373827734da2375afab9ad3
+ fb2bf11df41a072f;
+ 260c571b4a42bb
+ 8fdb233bfa6a5cfb
+ ""
+ 0bad7d95214ade49cb3b6f5fe8368131115c037ba323fe1dc815178487
+ b7abf514a519880bcf9a1dd906236193181274945f26eeea26de9a4480
+ 0a4c5b3dea189c9f;
+ 3f0eb5b647da67
+ 94c18b5337685a96
+ ed65b9aca338527ef19b09c063c46f88de9fd4
+ 1e72d7b97e23e6eabdff3bcd211499268878dbf30f1dad89d4b9b12012
+ abb5a85ee34c20c9ac26d5b84fb2079b949508c3a6c248aef713c7e3c8
+ 66f1833b4afd2bd8;
+ e4713df46795630e7952
+ d22bb02d7100b8b6
+ ""
+ ""
+ ""
+ be24074b27f49059;
+ 49377d20a8f083455b66
+ 3e4ee1315f3c8f2a
+ eb
+ ""
+ ""
+ ee190cc6ecad475c;
+ fa921451dcd1af5813b7
+ 0d30ce2f1fef6ef3
+ ""
+ 15
+ bb
+ 5a83e24c3f3d84e9;
+ d0798391805da08da3ae
+ fc5f8584b7c5e617
+ ""
+ 669c0f16e39815d4e9cfce3ed1ecdf3d264a7f16cb16c2e8
+ a573de0fdef866acaa2ebd0be9a101af7f8e4ce6d9f33a2a
+ f3acd5608b4d8863;
+ 15f422cdf0c8e30308be
+ 3c31e6bc58c0b7ca
+ dcb658b970e47479a684b5aefa69a4cd52147ed12ca98698
+ 1a874498ad0abef8bc4fcb70e27e98ef1f0446b42fb144d4
+ acb6678d5dcfe7373c937b1b743ac60d7b039ee405cc184d
+ 426f814ef7af424d;
+ 4b6d00f06dc188d472a7
+ 84e0c6f21195a3b9
+ ""
+ f4ae985511265febd11c164720eef9eb1c8dd0b00951f284649016ed00
+ 6b9981f8864012346d4faa801dc7d0aa35703d3a19fcbfd65c79509cc1
+ 4b2c765518bd12b4;
+ 456331854bc78bf43966
+ eb0cfa9138ddc399
+ 08445608fe95e81c2533e31c9c1a9851bc2810
+ d858cbbc8424d126b807e6daa089c3f9099c5ffb824173d7634c04226f
+ ade2fa7115805e2fe9464340d7b5a7c97c093ded512f5c7cec815ff278
+ af6dddac99d6a024;
+ 30cbb7f0e4a973a8cd
+ 190107314717a774
+ ""
+ ""
+ ""
+ 1bf75ebfe2f2c874;
+ 56f3ff669c732b58db
+ 8f48af65f7cc9e3f
+ b9
+ ""
+ ""
+ b5e6cebf8f565eb4;
+ 0e1721b730374ffc9b
+ c597f56ccbb2f294
+ ""
+ b3
+ 18
+ feee3b50ee01bc04;
+ 8766fc69f6a9f2c094
+ 5ffd505003cc0cae
+ ""
+ 9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911e32d65
+ e918a45ec5088f385ab211351a06495693bfb81dcd0d7749
+ 9a6e716945055b00;
+ cc1770a18cbfe6effd
+ 1ff6778554acf127
+ 0485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b
+ 480aa3a4c84cef64f6c9b53bf8f957f4b03cf43e89957f9a
+ b25ea7ed37027181c51ab3d374c9f2cf8dc6a5c275c93b11
+ 6b72bcad7a2cc4a4;
+ 3e8128f8743d16687b
+ 7bb8deb9bd205b70
+ ""
+ e04c091d205cdad9e9a79b1abf91b0851e5ca605ac8451399587011677
+ 45c3c8686b2cd92247a8afc0ca13a832de78417abbd11d3e7a687bc4cc
+ 6247cc4284c11080;
+ 508a15dde524af3e2b
+ ee0646541a42c2ec
+ ccb44d65bad397abfaf529ee41cf9a05c7efed
+ ef3401539c51d2a90bbf7f1bfc338ab0ef5746ea8fdcccd213e33f7e8a
+ be2975c04e206859c47b5380c0e22d177563ce76c47538d89ae0be19f9
+ 9cc636850cbc148f;
+}
+
+xtea-pmac1 {
+ 60d7bcda163547d348b7551195
+ ""
+ 5afaac6a8b1d8747;
+ e77022907dd1dff7dac5c9941d
+ 26
+ 586ad5dfb39d35c5;
+ d0c6eb14ad568f86edd1dc9268
+ eeee533285a6ed810c9b689daaa9060d2d4b6003062365b0
+ e6a7ee16109f3b0d;
+ a54364c76c160f11896c479484
+ 6ecfa14a7130c9f137120634c9519848a877ff
+ 320631d3f31f8840;
+ 77bf79192a5b50
+ ""
+ eeb3c7cb0d072322;
+ ade5d9cd739a3d
+ 1f
+ 377efb6339f47074;
+ 337f29549e6b0d
+ 27a4ba234085406a6136512061f7080cc07df0591d8fa21f
+ 23266ff9052777ea;
+ 2dd88374d8cde8
+ e160ad10997a21635c6d62c9269029df3e6057
+ 387edca755c71aa8;
+ acc87638f508046733d9
+ ""
+ f88c2d9748aafff6;
+ ff61cdbda3b3e9878731
+ eb
+ 5502443fc2d9e373;
+ fedd4705e505da1435dc
+ eaa7b1cc49ae1d50c38201a894476b3f102b752eb9529533
+ 722b4728cbe72195;
+ 966f27043eb621b7f65b
+ 000961040ef2f9b2fc5fa450727a9b542cde52
+ c4d4788b5aaaba15;
+ ebfda19d0ccc520f21
+ ""
+ df7b7666d395d55c;
+ 5eb57bb3a4f3ebbbb1
+ 8a
+ 28c63dbfb924352f;
+ c6c95a97a48030370c
+ 33d090c54215abd6b3ad54efc9a38378c5b93bf4f2aad260
+ df15e66620945a9d;
+ 5faee2b03fb648e27f
+ ff63102758fe2b69ac26afa3349829b9458630
+ 5017699c228b645c;
+}
+
+xtea-ocb3 {
+ 60d7bcda163547d348b7551195
+ e77022907dd1
+ ""
+ ""
+ ""
+ 5d2c01e9160963e2;
+ dff7dac5c9941d26d0c6eb14ad
+ 568f86edd1dc
+ 92
+ ""
+ ""
+ f4290b5fa1095a3b;
+ 68eeee533285a6ed810c9b689d
+ aaa9060d2d4b
+ ""
+ 60
+ 86
+ a0258d79cfe3419c;
+ 03062365b0a54364c76c160f11
+ 896c47
+ ""
+ 94846ecfa14a7130c9f137120634c9519848a877ff77bf79
+ 6610c7e7e150973b3af3229eaca70189ec0e13b564297b84
+ 235c7f65cfd0cda9;
+ 192a5b50ade5d9cd739a3d1f33
+ 7f29549e6b
+ 0d27a4ba234085406a6136512061f7080cc07df0591d8fa2
+ 1f2dd88374d8cde8e160ad10997a21635c6d62c9269029df
+ ea5f7d5a908f059911b6b766f706d5f3c9a1b7d5b4d42065
+ ba47585a0fa5b8d2;
+ 3e6057acc87638f508046733d9
+ ff61cdbda3b3
+ ""
+ e9878731ebfedd4705e505da1435dceaa7b1cc49ae1d50c38201a89447
+ 1eb152c297208c394377db7669f0147c95b8fac5b1b8607d9584253b23
+ d9340baabda4544b;
+ 6b3f102b752eb9529533966f27
+ 043eb621b7f6
+ 5b000961040ef2f9b2fc5fa450727a9b542cde
+ 52ebfda19d0ccc520f215eb57bb3a4f3ebbbb18ac6c95a97a48030370c
+ 67480201e5ad84d5c418b97dd662d14467346d3a41358000bcd2f70ad4
+ c401dcec1ed2f580;
+ 33d090c54215ab
+ d6b3ad54efc9
+ ""
+ ""
+ ""
+ 55b5295ceea5a2b0;
+ a38378c5b93bf4
+ f2aad2605fae
+ e2
+ ""
+ ""
+ 0f315886523d1ef8;
+ b03fb648e27fff
+ 63102758fe2b
+ ""
+ 69
+ f9
+ 6363d821109640b7;
+ ac26afa3349829
+ b94586
+ ""
+ 306fed54154f8f28523c03d4de1600157846b710ee72807a
+ 5d059d165b480d0bd30aa01fbc99b6c73bb78a97846f94e0
+ dd5e7c83be0625ef;
+ 2219bfb474fd71
+ d891f24bb6
+ 5d1563259f9eb53b571ea629c54d57dd2d42f70800df9fcb
+ aca48b77dba189196d1ebba10b0467cb9fc2712a199e533f
+ 02ba51adcc2bb6ba3ab41756291366f14f0cb20893fa39a9
+ 2b280bddba65b2fa;
+ a9156308cdec3f
+ 768281e040a9
+ ""
+ b9a222bd689aef66f5306ceb0c6b08ac8b0a22260c571b4a42bb8fdb23
+ cb82582817fa2dd3563bbc12c501093140d5df1fdbd0a319ad4f28cb28
+ 0da5ea5b1a5fdddd;
+ 3bfa6a5cfb0bad
+ 7d95214ade49
+ cb3b6f5fe8368131115c037ba323fe1dc81517
+ 84873f0eb5b647da6794c18b5337685a96ed65b9aca338527ef19b09c0
+ 2da5aa1294ef89aacc993ebd46ebec94a3feac279d392c27d92b0dbd30
+ f2713c40cf993ef3;
+ 63c46f88de9fd41e72d7
+ b97e23e6eabd
+ ""
+ ""
+ ""
+ f3501e0fcf27dbb5;
+ ff3bcd211499268878db
+ f30f1dad89d4
+ b9
+ ""
+ ""
+ 87b3dbbf4f9cc61d;
+ b12012e4713df4679563
+ 0e7952d22bb0
+ ""
+ 2d
+ c0
+ 5618eb373dd8374f;
+ 7100b8b649377d20a8f0
+ 83455b
+ ""
+ 663e4ee1315f3c8f2aebfa921451dcd1af5813b70d30ce2f
+ 99096150a0fe314a00a2336f097ad0f885f03c0b7cccd127
+ a66de7481d491c0c;
+ 1fef6ef315d079839180
+ 5da08da3ae
+ fc5f8584b7c5e617669c0f16e39815d4e9cfce3ed1ecdf3d
+ 264a7f16cb16c2e815f422cdf0c8e30308be3c31e6bc58c0
+ 3a678d2a777b2eaa8d344e42aedd5e722ffef69ba742ae1a
+ d6bc78818c3bb4a3;
+ b7cadcb658b970e47479
+ a684b5aefa69
+ ""
+ a4cd52147ed12ca986981a874498ad0abef8bc4fcb70e27e98ef1f0446
+ 85540182992781ca0104d764814e47ede859164af3405567d0c98bc7a0
+ 8857121b533f8a6b;
+ b42fb144d44b6d00f06d
+ c188d472a784
+ e0c6f21195a3b9f4ae985511265febd11c1647
+ 20eef9eb1c8dd0b00951f284649016ed00456331854bc78bf43966eb0c
+ 8e650a51a481be8fa4eb4277832e68fef19321017bfcb05543ccbd1278
+ b58014483ea856ce;
+ fa9138ddc399084456
+ 08fe95e81c25
+ ""
+ ""
+ ""
+ d6f325e74486f817;
+ 33e31c9c1a9851bc28
+ 10d858cbbc84
+ 24
+ ""
+ ""
+ 1b88f76f4bff9de0;
+ d126b807e6daa089c3
+ f9099c5ffb82
+ ""
+ 41
+ 8e
+ 1f85ea188d2fbe58;
+ 73d7634c04226f30cb
+ b7f0e4
+ ""
+ a973a8cd190107314717a77456f3ff669c732b58db8f48af
+ 8ac6753b0a1edc91a058b5bd8cd84f6e2d84a066d3263392
+ ea000b35774b2c35;
+ 65f7cc9e3fb90e1721
+ b730374ffc
+ 9bc597f56ccbb2f294b38766fc69f6a9f2c0945ffd505003
+ cc0cae9ce021a5f1fa4ffa91544485f1a1258b2b9b8f0911
+ 96bdfd04ff0191407c3b1d881eb29c718dbfc93ef7852b24
+ 3b4e8b97f9c055ea;
+ e32d65cc1770a18cbf
+ e6effd1ff677
+ ""
+ 8554acf1270485b203a3c1c4c967c0a458cb948bdd409b687fa3a6827b
+ 99ab24f8a320e106aa12864be588d6af0459d33e27a7b0ab9dcad9de9d
+ f740e2e18cae5773;
+ 480aa3a4c84cef64f6
+ c9b53bf8f957
+ f4b03cf43e89957f9a3e8128f8743d16687b7b
+ b8deb9bd205b70e04c091d205cdad9e9a79b1abf91b0851e5ca605ac84
+ 8d22fd98971cd873b0fab7bd557d5c4076eca3ed5f5acf7fa656bcc0b2
+ 16899233ed9068ed;
+}
+
+xtea-ocb3-mct {
+ 16 8cf53d7d6b43cdf1;
+ 14 5583f3a52de141d8;
+ 12 0b6565df07a02f3c;
+ 10 39da0a29f89a2699;
+ 8 24ea4af6cf4b09f8;
+ 6 6b4a51ac943cfa79;
+ 4 1f1b844caf0ddbae;
+ 16 6c4482111229;
+ 14 117519ba3a0f;
+ 12 ceb3bd9e235c;
+ 10 4d6a4907b3b5;
+ 8 6f7224393f2c;
+ 6 4629c2df66b4;
+ 4 c0ce4bd2a198;
+ 16 9ce1b811;
+ 14 b50aeacb;
+ 12 7c8e696b;
+ 10 8a6a0f17;
+ 8 f0422ae8;
+ 6 1c8cb415;
+ 4 b31dc24a;
+}
--- /dev/null
+#! /usr/bin/python
+
+from sys import argv, exit
+from struct import unpack, pack
+from itertools import izip
+import catacomb as C
+
+R = C.FibRand(0)
+
+###--------------------------------------------------------------------------
+### Utilities.
+
+def combs(things, k):
+ ii = range(k)
+ n = len(things)
+ while True:
+ yield [things[i] for i in ii]
+ for j in xrange(k):
+ if j == k - 1: lim = n
+ else: lim = ii[j + 1]
+ i = ii[j] + 1
+ if i < lim:
+ ii[j] = i
+ break
+ ii[j] = j
+ else:
+ return
+
+POLYMAP = {}
+
+def poly(nbits):
+ try: return POLYMAP[nbits]
+ except KeyError: pass
+ base = C.GF(0).setbit(nbits).setbit(0)
+ for k in xrange(1, nbits, 2):
+ for cc in combs(range(1, nbits), k):
+ p = base + sum(C.GF(0).setbit(c) for c in cc)
+ if p.irreduciblep(): POLYMAP[nbits] = p; return p
+ raise ValueError, nbits
+
+def prim(nbits):
+ ## No fancy way to do this: I'd need a much cleverer factoring algorithm
+ ## than I have in my pockets.
+ if nbits == 64: cc = [64, 4, 3, 1, 0]
+ elif nbits == 96: cc = [96, 10, 9, 6, 0]
+ elif nbits == 128: cc = [128, 7, 2, 1, 0]
+ elif nbits == 192: cc = [192, 15, 11, 5, 0]
+ elif nbits == 256: cc = [256, 10, 5, 2, 0]
+ else: raise ValueError, 'no field for %d bits' % nbits
+ p = C.GF(0)
+ for c in cc: p = p.setbit(c)
+ return p
+
+def Z(n):
+ return C.ByteString.zero(n)
+
+def mul_blk_gf(m, x, p): return ((C.GF.loadb(m)*x)%p).storeb((p.nbits + 6)/8)
+
+def with_lastp(it):
+ it = iter(it)
+ try: j = next(it)
+ except StopIteration: raise ValueError, 'empty iter'
+ lastp = False
+ while not lastp:
+ i = j
+ try: j = next(it)
+ except StopIteration: lastp = True
+ yield i, lastp
+
+def safehex(x):
+ if len(x): return hex(x)
+ else: return '""'
+
+def keylens(ksz):
+ sel = []
+ if isinstance(ksz, C.KeySZSet): kk = ksz.set
+ elif isinstance(ksz, C.KeySZRange): kk = range(ksz.min, ksz.max, ksz.mod)
+ elif isinstance(ksz, C.KeySZAny): kk = range(64); sel = [0]
+ kk = list(kk); kk = kk[:]
+ n = len(kk)
+ while n and len(sel) < 4:
+ i = R.range(n)
+ n -= 1
+ kk[i], kk[n] = kk[n], kk[i]
+ sel.append(kk[n])
+ return sel
+
+def pad0star(m, w):
+ n = len(m)
+ if not n: r = w
+ else: r = (-len(m))%w
+ if r: m += Z(r)
+ return C.ByteString(m)
+
+def pad10star(m, w):
+ r = w - len(m)%w
+ if r: m += '\x80' + Z(r - 1)
+ return C.ByteString(m)
+
+def ntz(i):
+ j = 0
+ while (i&1) == 0: i >>= 1; j += 1
+ return j
+
+def blocks(x, w):
+ v, i, n = [], 0, len(x)
+ while n - i > w:
+ v.append(C.ByteString(x[i:i + w]))
+ i += w
+ return v, C.ByteString(x[i:])
+
+EMPTY = C.bytes('')
+
+def blocks0(x, w):
+ v, tl = blocks(x, w)
+ if len(tl) == w: v.append(tl); tl = EMPTY
+ return v, tl
+
+def dummygen(bc): return []
+
+CUSTOM = {}
+
+###--------------------------------------------------------------------------
+### RC6.
+
+class RC6Cipher (type):
+ def __new__(cls, w, r):
+ name = 'rc6-%d/%d' % (w, r)
+ me = type(name, (RC6Base,), {})
+ me.name = name
+ me.r = r
+ me.w = w
+ me.blksz = w/2
+ me.keysz = C.KeySZRange(me.blksz, 1, 255, 1)
+ return me
+
+def rotw(w):
+ return w.bit_length() - 1
+
+def rol(w, x, n):
+ m0, m1 = C.MP(0).setbit(w - n) - 1, C.MP(0).setbit(n) - 1
+ return ((x&m0) << n) | (x >> (w - n))&m1
+
+def ror(w, x, n):
+ m0, m1 = C.MP(0).setbit(n) - 1, C.MP(0).setbit(w - n) - 1
+ return ((x&m0) << (w - n)) | (x >> n)&m1
+
+class RC6Base (object):
+
+ ## Magic constants.
+ P400 = C.MP(0xb7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d9045190cfef324e7738926cfbe5f4bf8d8d8c31d763da06)
+ Q400 = C.MP(0x9e3779b97f4a7c15f39cc0605cedc8341082276bf3a27251f86c6a11d0c18e952767f0b153d27b7f0347045b5bf1827f0188)
+
+ def __init__(me, k):
+
+ ## Build the magic numbers.
+ P = me.P400 >> (400 - me.w)
+ if P%2 == 0: P += 1
+ Q = me.Q400 >> (400 - me.w)
+ if Q%2 == 0: Q += 1
+ M = C.MP(0).setbit(me.w) - 1
+
+ ## Convert the key into words.
+ wb = me.w/8
+ c = (len(k) + wb - 1)/wb
+ kb, ktl = blocks(k, me.w/8)
+ L = map(C.MP.loadl, kb + [ktl])
+ assert c == len(L)
+
+ ## Build the subkey table.
+ me.d = rotw(me.w)
+ n = 2*me.r + 4
+ S = [(P + i*Q)&M for i in xrange(n)]
+
+ ##for j in xrange(c):
+ ## print 'L[%3d] = %s' % (j, hex(L[j]).upper()[2:].rjust(2*wb, '0'))
+ ##for i in xrange(n):
+ ## print 'S[%3d] = %s' % (i, hex(S[i]).upper()[2:].rjust(2*wb, '0'))
+
+ i = j = 0
+ A = B = C.MP(0)
+
+ for s in xrange(3*max(c, n)):
+ A = S[i] = rol(me.w, S[i] + A + B, 3)
+ B = L[j] = rol(me.w, L[j] + A + B, (A + B)%(1 << me.d))
+ ##print 'S[%3d] = %s' % (i, hex(S[i]).upper()[2:].rjust(2*wb, '0'))
+ ##print 'L[%3d] = %s' % (j, hex(L[j]).upper()[2:].rjust(2*wb, '0'))
+ i = (i + 1)%n
+ j = (j + 1)%c
+
+ ## Done.
+ me.s = S
+
+ def encrypt(me, x):
+ M = C.MP(0).setbit(me.w) - 1
+ a, b, c, d = map(C.MP.loadl, blocks0(x, me.blksz/4)[0])
+ b = (b + me.s[0])&M
+ d = (d + me.s[1])&M
+ ##print 'B = %s' % (hex(b).upper()[2:].rjust(me.w/4, '0'))
+ ##print 'D = %s' % (hex(d).upper()[2:].rjust(me.w/4, '0'))
+ for i in xrange(2, 2*me.r + 2, 2):
+ t = rol(me.w, 2*b*b + b, me.d)
+ u = rol(me.w, 2*d*d + d, me.d)
+ a = (rol(me.w, a ^ t, u%(1 << me.d)) + me.s[i + 0])&M
+ c = (rol(me.w, c ^ u, t%(1 << me.d)) + me.s[i + 1])&M
+ ##print 'A = %s' % (hex(a).upper()[2:].rjust(me.w/4, '0'))
+ ##print 'C = %s' % (hex(c).upper()[2:].rjust(me.w/4, '0'))
+ a, b, c, d = b, c, d, a
+ a = (a + me.s[2*me.r + 2])&M
+ c = (c + me.s[2*me.r + 3])&M
+ ##print 'A = %s' % (hex(a).upper()[2:].rjust(me.w/4, '0'))
+ ##print 'C = %s' % (hex(c).upper()[2:].rjust(me.w/4, '0'))
+ return C.ByteString(a.storel(me.blksz/4) + b.storel(me.blksz/4) +
+ c.storel(me.blksz/4) + d.storel(me.blksz/4))
+
+ def decrypt(me, x):
+ M = C.MP(0).setbit(me.w) - 1
+ a, b, c, d = map(C.MP.loadl, blocks0(x, me.blksz/4))
+ c = (c - me.s[2*me.r + 3])&M
+ a = (a - me.s[2*me.r + 2])&M
+ for i in xrange(2*me.r + 1, 1, -2):
+ a, b, c, d = d, a, b, c
+ u = rol(me.w, 2*d*d + d, me.d)
+ t = rol(me.w, 2*b*b + b, me.d)
+ c = ror(me.w, (c - me.s[i + 1])&M, t%(1 << me.d)) ^ u
+ a = ror(me.w, (a - me.s[i + 0])&M, u%(1 << me.d)) ^ t
+ a = (a + s[2*me.r + 2])&M
+ c = (c + s[2*me.r + 3])&M
+ return C.ByteString(a.storel(me.blksz/4) + b.storel(me.blksz/4) +
+ c.storel(me.blksz/4) + d.storel(me.blksz/4))
+
+for (w, r) in [(8, 16), (16, 16), (24, 16), (32, 16),
+ (32, 20), (48, 16), (64, 16), (96, 16), (128, 16),
+ (192, 16), (256, 16), (400, 16)]:
+ CUSTOM['rc6-%d/%d' % (w, r)] = RC6Cipher(w, r)
+
+###--------------------------------------------------------------------------
+### OMAC (or CMAC).
+
+def omac_masks(E):
+ blksz = E.__class__.blksz
+ p = poly(8*blksz)
+ z = Z(blksz)
+ L = E.encrypt(z)
+ m0 = mul_blk_gf(L, 2, p)
+ m1 = mul_blk_gf(m0, 2, p)
+ return m0, m1
+
+def dump_omac(E):
+ blksz = E.__class__.blksz
+ m0, m1 = omac_masks(E)
+ print 'L = %s' % hex(E.encrypt(Z(blksz)))
+ print 'm0 = %s' % hex(m0)
+ print 'm1 = %s' % hex(m1)
+ for t in xrange(3):
+ print 'v%d = %s' % (t, hex(E.encrypt(C.MP(t).storeb(blksz))))
+ print 'z%d = %s' % (t, hex(omac(E, t, '')))
+
+def omac(E, t, m):
+ blksz = E.__class__.blksz
+ m0, m1 = omac_masks(E)
+ a = Z(blksz)
+ if t is not None: m = C.MP(t).storeb(blksz) + m
+ v, tl = blocks(m, blksz)
+ for x in v: a = E.encrypt(a ^ x)
+ r = blksz - len(tl)
+ if r == 0:
+ a = E.encrypt(a ^ tl ^ m0)
+ else:
+ pad = pad10star(tl, blksz)
+ a = E.encrypt(a ^ pad ^ m1)
+ return a
+
+def cmac(E, m):
+ if VERBOSE: dump_omac(E)
+ return omac(E, None, m),
+
+def cmacgen(bc):
+ return [(0,), (1,),
+ (3*bc.blksz,),
+ (3*bc.blksz - 5,)]
+
+###--------------------------------------------------------------------------
+### Counter mode.
+
+def ctr(E, m, c0):
+ blksz = E.__class__.blksz
+ y = C.WriteBuffer()
+ c = C.MP.loadb(c0)
+ while y.size < len(m):
+ y.put(E.encrypt(c.storeb(blksz)))
+ c += 1
+ return C.ByteString(m) ^ C.ByteString(y)[:len(m)]
+
+###--------------------------------------------------------------------------
+### GCM.
+
+def gcm_mangle(x):
+ y = C.WriteBuffer()
+ for b in x:
+ b = ord(b)
+ bb = 0
+ for i in xrange(8):
+ bb <<= 1
+ if b&1: bb |= 1
+ b >>= 1
+ y.putu8(bb)
+ return C.ByteString(y)
+
+def gcm_mul(x, y):
+ w = len(x)
+ p = poly(8*w)
+ u, v = C.GF.loadl(gcm_mangle(x)), C.GF.loadl(gcm_mangle(y))
+ z = (u*v)%p
+ return gcm_mangle(z.storel(w))
+
+def gcm_pow(x, n):
+ w = len(x)
+ p = poly(8*w)
+ u = C.GF.loadl(gcm_mangle(x))
+ z = pow(u, n, p)
+ return gcm_mangle(z.storel(w))
+
+def gcm_ctr(E, m, c0):
+ y = C.WriteBuffer()
+ pre = c0[:-4]
+ c, = unpack('>L', c0[-4:])
+ while y.size < len(m):
+ c += 1
+ y.put(E.encrypt(pre + pack('>L', c)))
+ return C.ByteString(m) ^ C.ByteString(y)[:len(m)]
+
+def g(what, x, m, a0 = None):
+ n = len(x)
+ if a0 is None: a = Z(n)
+ else: a = a0
+ i = 0
+ for b in blocks0(m, n)[0]:
+ a = gcm_mul(a ^ b, x)
+ if VERBOSE: print '%s[%d] = %s -> %s' % (what, i, hex(b), hex(a))
+ i += 1
+ return a
+
+def gcm_pad(w, x):
+ return C.ByteString(x + Z(-len(x)%w))
+
+def gcm_lens(w, a, b):
+ if w < 12: n = w
+ else: n = w/2
+ return C.ByteString(C.MP(a).storeb(n) + C.MP(b).storeb(n))
+
+def ghash(whata, whatb, x, a, b):
+ w = len(x)
+ ha = g(whata, x, gcm_pad(w, a))
+ hb = g(whatb, x, gcm_pad(w, b))
+ if a:
+ hc = gcm_mul(ha, gcm_pow(x, (len(b) + w - 1)/w)) ^ hb
+ if VERBOSE: print '%s || %s -> %s' % (whata, whatb, hex(hc))
+ else:
+ hc = hb
+ return g(whatb, x, gcm_lens(w, 8*len(a), 8*len(b)), hc)
+
+def gcmenc(E, n, h, m, tsz = None):
+ w = E.__class__.blksz
+ x = E.encrypt(Z(w))
+ if VERBOSE: print 'x = %s' % hex(x)
+ if len(n) + 4 == w: c0 = C.ByteString(n + pack('>L', 1))
+ else: c0 = ghash('?', 'n', x, EMPTY, n)
+ if VERBOSE: print 'c0 = %s' % hex(c0)
+ y = gcm_ctr(E, m, c0)
+ t = ghash('h', 'y', x, h, y) ^ E.encrypt(c0)
+ return y, t
+
+def gcmdec(E, n, h, y, t):
+ w = E.__class__.blksz
+ x = E.encrypt(Z(w))
+ if VERBOSE: print 'x = %s' % hex(x)
+ if len(n) + 4 == w: c0 = C.ByteString(n + pack('>L', 1))
+ else: c0 = ghash('?', 'n', x, EMPTY, n)
+ if VERBOSE: print 'c0 = %s' % hex(c0)
+ m = gcm_ctr(E, y, c0)
+ tt = ghash('h', 'y', x, h, y) ^ E.encrypt(c0)
+ if t == tt: return m,
+ else: return None,
+
+def gcmgen(bc):
+ return [(0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1),
+ (bc.blksz, 3*bc.blksz, 3*bc.blksz),
+ (bc.blksz - 4, bc.blksz + 3, 3*bc.blksz + 9),
+ (bc.blksz - 1, 3*bc.blksz - 5, 3*bc.blksz + 5)]
+
+def gcm_mul_tests(nbits):
+ print 'gcm-mul%d {' % nbits
+ for i in xrange(64):
+ x = R.block(nbits/8)
+ y = R.block(nbits/8)
+ z = gcm_mul(x, y)
+ print ' %s\n %s\n %s;' % (hex(x), hex(y), hex(z))
+ print '}'
+
+###--------------------------------------------------------------------------
+### CCM.
+
+def stbe(n, w): return C.MP(n).storeb(w)
+
+def ccm_fmthdr(blksz, n, hsz, msz, tsz):
+ b = C.WriteBuffer()
+ if blksz == 8:
+ q = blksz - len(n) - 1
+ f = 0
+ if hsz: f |= 0x40
+ f |= (tsz - 1) << 3
+ f |= q - 1
+ b.putu8(f).put(n).put(stbe(msz, q))
+ elif blksz == 16:
+ q = blksz - len(n) - 1
+ f = 0
+ if hsz: f |= 0x40
+ f |= (tsz - 2)/2 << 3
+ f |= q - 1
+ b.putu8(f).put(n).put(stbe(msz, q))
+ else:
+ q = blksz - len(n) - 2
+ f0 = f1 = 0
+ if hsz: f1 |= 0x80
+ f0 |= tsz
+ f1 |= q
+ b.putu8(f0).putu8(f1).put(n).put(stbe(msz, q))
+ b = C.ByteString(b)
+ if VERBOSE: print 'hdr = %s' % hex(b)
+ return b
+
+def ccm_fmtctr(blksz, n, i = 0):
+ b = C.WriteBuffer()
+ if blksz == 8 or blksz == 16:
+ q = blksz - len(n) - 1
+ b.putu8(q - 1).put(n).put(stbe(i, q))
+ else:
+ q = blksz - len(n) - 2
+ b.putu8(0).putu8(q).put(n).put(stbe(i, q))
+ b = C.ByteString(b)
+ if VERBOSE: print 'ctr = %s' % hex(b)
+ return b
+
+def ccmaad(b, h, blksz):
+ hsz = len(h)
+ if not hsz: pass
+ elif hsz < 0xfffe: b.putu16(hsz)
+ elif hsz <= 0xffffffff: b.putu16(0xfffe).putu32(hsz)
+ else: b.putu16(0xffff).putu64(hsz)
+ b.put(h); b.zero((-b.size)%blksz)
+
+def ccmenc(E, n, h, m, tsz = None):
+ blksz = E.__class__.blksz
+ if tsz is None: tsz = blksz
+ b = C.WriteBuffer()
+ b.put(ccm_fmthdr(blksz, n, len(h), len(m), tsz))
+ ccmaad(b, h, blksz)
+ b.put(m); b.zero((-b.size)%blksz)
+ b = C.ByteString(b)
+ a = Z(blksz)
+ v, _ = blocks0(b, blksz)
+ i = 0
+ for x in v:
+ a = E.encrypt(a ^ x)
+ if VERBOSE:
+ print 'b[%d] = %s' % (i, hex(x))
+ print 'a[%d] = %s' % (i + 1, hex(a))
+ i += 1
+ y = ctr(E, a + m, ccm_fmtctr(blksz, n))
+ return C.ByteString(y[blksz:]), C.ByteString(y[0:tsz])
+
+def ccmdec(E, n, h, y, t):
+ blksz = E.__class__.blksz
+ tsz = len(t)
+ b = C.WriteBuffer()
+ b.put(ccm_fmthdr(blksz, n, len(h), len(y), tsz))
+ ccmaad(b, h, blksz)
+ mm = ctr(E, t + Z(blksz - tsz) + y, ccm_fmtctr(blksz, n))
+ u, m = C.ByteString(mm[0:tsz]), C.ByteString(mm[blksz:])
+ b.put(m); b.zero((-b.size)%blksz)
+ b = C.ByteString(b)
+ a = Z(blksz)
+ v, _ = blocks0(b, blksz)
+ i = 0
+ for x in v:
+ a = E.encrypt(a ^ x)
+ if VERBOSE:
+ print 'b[%d] = %s' % (i, hex(x))
+ print 'a[%d] = %s' % (i + 1, hex(a))
+ i += 1
+ if u == a[:tsz]: return m,
+ else: return None,
+
+def ccmgen(bc):
+ bsz = bc.blksz
+ return [(bsz - 5, 0, 0, 4), (bsz - 5, 1, 0, 4), (bsz - 5, 0, 1, 4),
+ (bsz/2 + 1, 3*bc.blksz, 3*bc.blksz),
+ (bsz/2 + 1, 3*bc.blksz - 5, 3*bc.blksz + 5)]
+
+###--------------------------------------------------------------------------
+### EAX.
+
+def eaxenc(E, n, h, m, tsz = None):
+ if VERBOSE:
+ print 'k = %s' % hex(k)
+ print 'n = %s' % hex(n)
+ print 'h = %s' % hex(h)
+ print 'm = %s' % hex(m)
+ dump_omac(E)
+ if tsz is None: tsz = E.__class__.blksz
+ c0 = omac(E, 0, n)
+ y = ctr(E, m, c0)
+ ht = omac(E, 1, h)
+ yt = omac(E, 2, y)
+ if VERBOSE:
+ print 'c0 = %s' % hex(c0)
+ print 'ht = %s' % hex(ht)
+ print 'yt = %s' % hex(yt)
+ return y, C.ByteString((c0 ^ ht ^ yt)[:tsz])
+
+def eaxdec(E, n, h, y, t):
+ if VERBOSE:
+ print 'k = %s' % hex(k)
+ print 'n = %s' % hex(n)
+ print 'h = %s' % hex(h)
+ print 'y = %s' % hex(y)
+ print 't = %s' % hex(t)
+ dump_omac(E)
+ c0 = omac(E, 0, n)
+ m = ctr(E, y, c0)
+ ht = omac(E, 1, h)
+ yt = omac(E, 2, y)
+ if VERBOSE:
+ print 'c0 = %s' % hex(c0)
+ print 'ht = %s' % hex(ht)
+ print 'yt = %s' % hex(yt)
+ if t == (c0 ^ ht ^ yt)[:len(t)]: return m,
+ else: return None,
+
+def eaxgen(bc):
+ return [(0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1),
+ (bc.blksz, 3*bc.blksz, 3*bc.blksz),
+ (bc.blksz - 1, 3*bc.blksz - 5, 3*bc.blksz + 5)]
+
+###--------------------------------------------------------------------------
+### PMAC.
+
+def ocb_masks(E):
+ blksz = E.__class__.blksz
+ p = poly(8*blksz)
+ x = C.GF(2); xinv = p.modinv(x)
+ z = Z(blksz)
+ L = E.encrypt(z)
+ Lxinv = mul_blk_gf(L, xinv, p)
+ Lgamma = 66*[L]
+ for i in xrange(1, len(Lgamma)):
+ Lgamma[i] = mul_blk_gf(Lgamma[i - 1], x, p)
+ return Lgamma, Lxinv
+
+def dump_ocb(E):
+ Lgamma, Lxinv = ocb_masks(E)
+ print 'L x^-1 = %s' % hex(Lxinv)
+ for i, lg in enumerate(Lgamma[:16]):
+ print 'L x^%d = %s' % (i, hex(lg))
+
+def pmac1(E, m):
+ blksz = E.__class__.blksz
+ Lgamma, Lxinv = ocb_masks(E)
+ a = o = Z(blksz)
+ i = 0
+ v, tl = blocks(m, blksz)
+ for x in v:
+ i += 1
+ b = ntz(i)
+ o ^= Lgamma[b]
+ a ^= E.encrypt(x ^ o)
+ if VERBOSE:
+ print 'Z[%d]: %d -> %s' % (i, b, hex(o))
+ print 'A[%d]: %s' % (i, hex(a))
+ if len(tl) == blksz: a ^= tl ^ Lxinv
+ else: a ^= pad10star(tl, blksz)
+ return E.encrypt(a)
+
+def pmac2(E, m):
+ blksz = E.__class__.blksz
+ p = prim(8*blksz)
+ L = E.encrypt(Z(blksz))
+ o = mul_blk_gf(L, 10, p)
+ a = Z(blksz)
+ v, tl = blocks(m, blksz)
+ for x in v:
+ a ^= E.encrypt(x ^ o)
+ o = mul_blk_gf(o, 2, p)
+ if len(tl) == blksz: a ^= tl ^ mul_blk_gf(o, 3, p)
+ else: a ^= pad10star(tl, blksz) ^ mul_blk_gf(o, 5, p)
+ return E.encrypt(a)
+
+def ocb3_masks(E):
+ Lgamma, _ = ocb_masks(E)
+ Lstar = Lgamma[0]
+ Ldollar = Lgamma[1]
+ return Lstar, Ldollar, Lgamma[2:]
+
+def dump_ocb3(E):
+ Lstar, Ldollar, Lgamma = ocb3_masks(E)
+ print 'L_* = %s' % hex(Lstar)
+ print 'L_$ = %s' % hex(Ldollar)
+ for i, lg in enumerate(Lgamma[:16]):
+ print 'L x^%d = %s' % (i, hex(lg))
+
+def pmac3(E, m):
+ ## Note that `PMAC3' is /not/ a secure MAC. It depends on other parts of
+ ## OCB3 to prevent a rather easy linear-algebra attack.
+ blksz = E.__class__.blksz
+ Lstar, Ldollar, Lgamma = ocb3_masks(E)
+ a = o = Z(blksz)
+ i = 0
+ v, tl = blocks0(m, blksz)
+ for x in v:
+ i += 1
+ b = ntz(i)
+ o ^= Lgamma[b]
+ a ^= E.encrypt(x ^ o)
+ if VERBOSE:
+ print 'Z[%d]: %d -> %s' % (i, b, hex(o))
+ print 'A[%d]: %s' % (i, hex(a))
+ if tl:
+ o ^= Lstar
+ a ^= E.encrypt(pad10star(tl, blksz) ^ o)
+ if VERBOSE:
+ print 'Z[%d]: * -> %s' % (i, hex(o))
+ print 'A[%d]: %s' % (i, hex(a))
+ return a
+
+def pmac1_pub(E, m):
+ if VERBOSE: dump_ocb(E)
+ return pmac1(E, m),
+
+def pmacgen(bc):
+ return [(0,), (1,),
+ (3*bc.blksz,),
+ (3*bc.blksz - 5,)]
+
+###--------------------------------------------------------------------------
+### OCB.
+
+def ocb1enc(E, n, h, m, tsz = None):
+ ## This is OCB1.PMAC1 from Rogaway's `Authenticated-Encryption with
+ ## Associated-Data'.
+ blksz = E.__class__.blksz
+ if VERBOSE: dump_ocb(E)
+ Lgamma, Lxinv = ocb_masks(E)
+ if tsz is None: tsz = blksz
+ a = Z(blksz)
+ o = E.encrypt(n ^ Lgamma[0])
+ if VERBOSE: print 'R = %s' % hex(o)
+ i = 0
+ y = C.WriteBuffer()
+ v, tl = blocks(m, blksz)
+ for x in v:
+ i += 1
+ b = ntz(i)
+ o ^= Lgamma[b]
+ a ^= x
+ if VERBOSE:
+ print 'Z[%d]: %d -> %s' % (i, b, hex(o))
+ print 'A[%d]: %s' % (i, hex(a))
+ y.put(E.encrypt(x ^ o) ^ o)
+ i += 1
+ b = ntz(i)
+ o ^= Lgamma[b]
+ n = len(tl)
+ if VERBOSE:
+ print 'Z[%d]: %d -> %s' % (i, b, hex(o))
+ print 'LEN = %s' % hex(C.MP(8*n).storeb(blksz))
+ yfinal = E.encrypt(C.MP(8*n).storeb(blksz) ^ Lxinv ^ o)
+ cfinal = tl ^ yfinal[:n]
+ a ^= o ^ (tl + yfinal[n:])
+ y.put(cfinal)
+ t = E.encrypt(a)
+ if h: t ^= pmac1(E, h)
+ return C.ByteString(y), C.ByteString(t[:tsz])
+
+def ocb1dec(E, n, h, y, t):
+ ## This is OCB1.PMAC1 from Rogaway's `Authenticated-Encryption with
+ ## Associated-Data'.
+ blksz = E.__class__.blksz
+ if VERBOSE: dump_ocb(E)
+ Lgamma, Lxinv = ocb_masks(E)
+ a = Z(blksz)
+ o = E.encrypt(n ^ Lgamma[0])
+ if VERBOSE: print 'R = %s' % hex(o)
+ i = 0
+ m = C.WriteBuffer()
+ v, tl = blocks(y, blksz)
+ for x in v:
+ i += 1
+ b = ntz(i)
+ o ^= Lgamma[b]
+ if VERBOSE:
+ print 'Z[%d]: %d -> %s' % (i, b, hex(o))
+ print 'A[%d]: %s' % (i, hex(a))
+ u = E.decrypt(x ^ o) ^ o
+ m.put(u)
+ a ^= u
+ i += 1
+ b = ntz(i)
+ o ^= Lgamma[b]
+ n = len(tl)
+ if VERBOSE:
+ print 'Z[%d]: %d -> %s' % (i, b, hex(o))
+ print 'LEN = %s' % hex(C.MP(8*n).storeb(blksz))
+ yfinal = E.encrypt(C.MP(8*n).storeb(blksz) ^ Lxinv ^ o)
+ mfinal = tl ^ yfinal[:n]
+ a ^= o ^ (mfinal + yfinal[n:])
+ m.put(mfinal)
+ u = E.encrypt(a)
+ if h: u ^= pmac1(E, h)
+ if t == u[:len(t)]: return C.ByteString(m),
+ else: return None,
+
+def ocb2enc(E, n, h, m, tsz = None):
+ ## For OCB2, it's important for security that n = log_x (x + 1) is large in
+ ## the field representations of GF(2^w) used -- in fact, we need more, that
+ ## i n (mod 2^w - 1) is large for i in {4, -3, -2, -1, 1, 2, 3, 4}. The
+ ## original paper lists the values for 64 and 128, but we support other
+ ## block sizes, so here's the result of the (rather large, in some cases)
+ ## computation.
+ ##
+ ## Block size log_x (x + 1)
+ ##
+ ## 64 9686038906114705801
+ ## 96 63214690573408919568138788065
+ ## 128 338793687469689340204974836150077311399
+ ## 192 161110085006042185925119981866940491651092686475226538785
+ ## 256 22928580326165511958494515843249267194111962539778797914076675796261938307298
+
+ blksz = E.__class__.blksz
+ if tsz is None: tsz = blksz
+ p = prim(8*blksz)
+ L = E.encrypt(n)
+ o = mul_blk_gf(L, 2, p)
+ a = Z(blksz)
+ v, tl = blocks(m, blksz)
+ y = C.WriteBuffer()
+ for x in v:
+ a ^= x
+ y.put(E.encrypt(x ^ o) ^ o)
+ o = mul_blk_gf(o, 2, p)
+ n = len(tl)
+ yfinal = E.encrypt(C.MP(8*n).storeb(blksz) ^ o)
+ cfinal = tl ^ yfinal[:n]
+ a ^= (tl + yfinal[n:]) ^ mul_blk_gf(o, 3, p)
+ y.put(cfinal)
+ t = E.encrypt(a)
+ if h: t ^= pmac2(E, h)
+ return C.ByteString(y), C.ByteString(t[:tsz])
+
+def ocb2dec(E, n, h, y, t):
+ blksz = E.__class__.blksz
+ p = prim(8*blksz)
+ L = E.encrypt(n)
+ o = mul_blk_gf(L, 2, p)
+ a = Z(blksz)
+ v, tl = blocks(y, blksz)
+ m = C.WriteBuffer()
+ for x in v:
+ u = E.encrypt(x ^ o) ^ o
+ y.put(u)
+ a ^= u
+ o = mul_blk_gf(o, 2, p)
+ n = len(tl)
+ yfinal = E.encrypt(C.MP(8*n).storeb(blksz) ^ o)
+ mfinal = tl ^ yfinal[:n]
+ a ^= (mfinal + yfinal[n:]) ^ mul_blk_gf(o, 3, p)
+ m.put(mfinal)
+ u = E.encrypt(a)
+ if h: u ^= pmac2(E, h)
+ if t == u[:len(t)]: return C.ByteString(m),
+ else: return None,
+
+OCB3_STRETCH = { 4: ( 4, 17),
+ 8: ( 5, 25),
+ 12: ( 6, 33),
+ 16: ( 6, 8),
+ 24: ( 7, 40),
+ 32: ( 8, 1),
+ 48: ( 8, 80),
+ 64: ( 8, 176),
+ 96: ( 9, 160),
+ 128: ( 9, 352),
+ 200: (10, 192) }
+
+def ocb3nonce(E, n, tsz):
+
+ ## Figure out how much we need to glue onto the nonce. This ends up being
+ ## [t mod w]_v || 0^p || 1 || N, where w is the block size in bits, t is
+ ## the tag length in bits, v = floor(log_2(w - 1)) + 1, and p = w - l(N) -
+ ## v - 1. But this is an annoying way to think about it because of the
+ ## byte misalignment. Instead, think of it as a byte-aligned prefix
+ ## encoding the tag and an `is the nonce full-length' flag, followed by
+ ## optional padding, and then the nonce:
+ ##
+ ## F || N if l(N) = w - f
+ ## F || 0^p || 1 || N otherwise
+ ##
+ ## where F is [t mod w]_v || 0^{f-v-1} || b; f = floor(log_2(w - 1)) + 2;
+ ## b is 1 if l(N) = w - f, or 0 otherwise; and p = w - f - l(N) - 1.
+ blksz = E.__class__.blksz
+ tszbits = min(C.MP(8*blksz - 1).nbits, 8)
+ fwd = tszbits/8 + 1
+ f = 8*(tsz%blksz) << + 8*fwd - tszbits
+
+ ## Form the augmented nonce.
+ nb = C.WriteBuffer()
+ nsz, nwd = len(n), blksz - fwd
+ if nsz == nwd: f |= 1
+ nb.put(C.MP(f).storeb(fwd))
+ if nsz < nwd: nb.zero(nwd - nsz - 1).putu8(1)
+ nb.put(n)
+ nn = C.ByteString(nb)
+ if VERBOSE: print 'aug-nonce = %s' % hex(nn)
+
+ ## Calculate the initial offset.
+ split, shift = OCB3_STRETCH[blksz]
+ t2pw = C.MP(0).setbit(8*blksz) - 1
+ lomask = (C.MP(0).setbit(split) - 1)
+ himask = ~lomask
+ top, bottom = nn&himask.storeb2c(blksz), C.MP.loadb(nn)&lomask
+ ktop = C.MP.loadb(E.encrypt(top))
+ stretch = (ktop << 8*blksz) | (ktop ^ (ktop << shift)&t2pw)
+ o = (stretch >> 8*blksz - bottom).storeb(blksz)
+ if VERBOSE:
+ print 'stretch = %s' % hex(stretch.storeb(2*blksz))
+ print 'Z[0] = %s' % hex(o)
+
+ return o
+
+def ocb3enc(E, n, h, m, tsz = None):
+ blksz = E.__class__.blksz
+ if tsz is None: tsz = blksz
+ Lstar, Ldollar, Lgamma = ocb3_masks(E)
+ if VERBOSE: dump_ocb3(E)
+
+ ## Set things up.
+ o = ocb3nonce(E, n, tsz)
+ a = C.ByteString.zero(blksz)
+
+ ## Split the message into blocks.
+ i = 0
+ y = C.WriteBuffer()
+ v, tl = blocks0(m, blksz)
+ for x in v:
+ i += 1
+ b = ntz(i)
+ o ^= Lgamma[b]
+ a ^= x
+ if VERBOSE:
+ print 'Z[%d]: %d -> %s' % (i, b, hex(o))
+ print 'A[%d]: %s' % (i, hex(a))
+ y.put(E.encrypt(x ^ o) ^ o)
+ if tl:
+ o ^= Lstar
+ n = len(tl)
+ pad = E.encrypt(o)
+ a ^= pad10star(tl, blksz)
+ if VERBOSE:
+ print 'Z[%d]: * -> %s' % (i, hex(o))
+ print 'A[%d]: %s' % (i, hex(a))
+ y.put(tl ^ pad[0:n])
+ o ^= Ldollar
+ t = E.encrypt(a ^ o) ^ pmac3(E, h)
+ return C.ByteString(y), C.ByteString(t[:tsz])
+
+def ocb3dec(E, n, h, y, t):
+ blksz = E.__class__.blksz
+ tsz = len(t)
+ Lstar, Ldollar, Lgamma = ocb3_masks(E)
+ if VERBOSE: dump_ocb3(E)
+
+ ## Set things up.
+ o = ocb3nonce(E, n, tsz)
+ a = C.ByteString.zero(blksz)
+
+ ## Split the message into blocks.
+ i = 0
+ m = C.WriteBuffer()
+ v, tl = blocks0(y, blksz)
+ for x in v:
+ i += 1
+ b = ntz(i)
+ o ^= Lgamma[b]
+ if VERBOSE:
+ print 'Z[%d]: %d -> %s' % (i, b, hex(o))
+ print 'A[%d]: %s' % (i, hex(a))
+ u = E.encrypt(x ^ o) ^ o
+ m.put(u)
+ a ^= u
+ if tl:
+ o ^= Lstar
+ n = len(tl)
+ pad = E.encrypt(o)
+ if VERBOSE:
+ print 'Z[%d]: * -> %s' % (i, hex(o))
+ print 'A[%d]: %s' % (i, hex(a))
+ u = tl ^ pad[0:n]
+ m.put(u)
+ a ^= pad10star(u, blksz)
+ o ^= Ldollar
+ u = E.encrypt(a ^ o) ^ pmac3(E, h)
+ if t == u[:tsz]: return C.ByteString(m),
+ else: return None,
+
+def ocbgen(bc):
+ w = bc.blksz
+ return [(w, 0, 0), (w, 1, 0), (w, 0, 1),
+ (w, 0, 3*w),
+ (w, 3*w, 3*w),
+ (w, 0, 3*w + 5),
+ (w, 3*w - 5, 3*w + 5)]
+
+def ocb3gen(bc):
+ w = bc.blksz
+ return [(w - 2, 0, 0), (w - 2, 1, 0), (w - 2, 0, 1),
+ (w - 5, 0, 3*w),
+ (w - 3, 3*w, 3*w),
+ (w - 2, 0, 3*w + 5),
+ (w - 2, 3*w - 5, 3*w + 5)]
+
+def ocb3_mct(bc, ksz, tsz):
+ k = C.ByteString(C.WriteBuffer().zero(ksz - 4).putu32(8*tsz))
+ E = bc(k)
+ n = C.MP(1)
+ nw = bc.blksz - 4
+ cbuf = C.WriteBuffer()
+ for i in xrange(128):
+ s = C.ByteString.zero(i)
+ y, t = ocb3enc(E, n.storeb(nw), s, s, tsz); n += 1; cbuf.put(y).put(t)
+ y, t = ocb3enc(E, n.storeb(nw), EMPTY, s, tsz); n += 1; cbuf.put(y).put(t)
+ y, t = ocb3enc(E, n.storeb(nw), s, EMPTY, tsz); n += 1; cbuf.put(y).put(t)
+ _, t = ocb3enc(E, n.storeb(nw), C.ByteString(cbuf), EMPTY, tsz)
+ print hex(t)
+
+def ocb3_mct2(bc):
+ k = C.bytes('000102030405060708090a0b0c0d0e0f')
+ E = bc(k)
+ tsz = min(E.blksz, 32)
+ n = C.MP(1)
+ cbuf = C.WriteBuffer()
+ for i in xrange(128):
+ sbuf = C.WriteBuffer()
+ for j in xrange(i): sbuf.putu8(j)
+ s = C.ByteString(sbuf)
+ y, t = ocb3enc(E, n.storeb(2), s, s, tsz); n += 1; cbuf.put(y).put(t)
+ y, t = ocb3enc(E, n.storeb(2), EMPTY, s, tsz); n += 1; cbuf.put(y).put(t)
+ y, t = ocb3enc(E, n.storeb(2), s, EMPTY, tsz); n += 1; cbuf.put(y).put(t)
+ _, t = ocb3enc(E, n.storeb(2), C.ByteString(cbuf), EMPTY, tsz)
+ print hex(t)
+
+###--------------------------------------------------------------------------
+### Main program.
+
+class struct (object):
+ def __init__(me, **kw):
+ me.__dict__.update(kw)
+
+binarg = struct(mk = R.block, parse = C.bytes, show = safehex)
+intarg = struct(mk = lambda x: x, parse = int, show = None)
+
+MODEMAP = { 'eax-enc': (eaxgen, 3*[binarg] + [intarg], eaxenc),
+ 'eax-dec': (dummygen, 4*[binarg], eaxdec),
+ 'ccm-enc': (ccmgen, 3*[binarg] + [intarg], ccmenc),
+ 'ccm-dec': (dummygen, 4*[binarg], ccmdec),
+ 'cmac': (cmacgen, [binarg], cmac),
+ 'gcm-enc': (gcmgen, 3*[binarg] + [intarg], gcmenc),
+ 'gcm-dec': (dummygen, 4*[binarg], gcmdec),
+ 'ocb1-enc': (ocbgen, 3*[binarg] + [intarg], ocb1enc),
+ 'ocb1-dec': (dummygen, 4*[binarg], ocb1dec),
+ 'ocb2-enc': (ocbgen, 3*[binarg] + [intarg], ocb2enc),
+ 'ocb2-dec': (dummygen, 4*[binarg], ocb2dec),
+ 'ocb3-enc': (ocb3gen, 3*[binarg] + [intarg], ocb3enc),
+ 'ocb3-dec': (dummygen, 4*[binarg], ocb3dec),
+ 'pmac1': (pmacgen, [binarg], pmac1_pub) }
+
+mode = argv[1]
+if len(argv) == 3 and mode == 'gcm-mul':
+ VERBOSE = False
+ nbits = int(argv[2])
+ gcm_mul_tests(nbits)
+ exit(0)
+bc = None
+for d in CUSTOM, C.gcprps:
+ try: bc = d[argv[2]]
+ except KeyError: pass
+ else: break
+if bc is None: raise KeyError, argv[2]
+if len(argv) == 5 and mode == 'ocb3-mct':
+ VERBOSE = False
+ ksz, tsz = int(argv[3]), int(argv[4])
+ ocb3_mct(bc, ksz, tsz)
+ exit(0)
+if len(argv) == 3 and mode == 'ocb3-mct2':
+ VERBOSE = False
+ ocb3_mct2(bc)
+ exit(0)
+if len(argv) == 3:
+ VERBOSE = False
+ gen, argty, func = MODEMAP[mode]
+ if mode.endswith('-enc'): mode = mode[:-4]
+ print '%s-%s {' % (bc.name, mode)
+ for ksz in keylens(bc.keysz):
+ for argvals in gen(bc):
+ k = R.block(ksz)
+ args = [t.mk(a) for t, a in izip(argty, argvals)]
+ rets = func(bc(k), *args)
+ print ' %s' % safehex(k)
+ for t, a in izip(argty, args):
+ if t.show: print ' %s' % t.show(a)
+ for r, lastp in with_lastp(rets):
+ print ' %s%s' % (safehex(r), lastp and ';' or '')
+ print '}'
+else:
+ VERBOSE = True
+ k = C.bytes(argv[3])
+ gen, argty, func = MODEMAP[mode]
+ args = [t.parse(a) for t, a in izip(argty, argv[4:])]
+ rets = func(bc(k), *args)
+ for r in rets:
+ if r is None: print "X"
+ else: print hex(r)
+
+###----- That's all, folks --------------------------------------------------
--- /dev/null
+#! /usr/bin/python
+### -*- coding: utf-8 -*-
+
+from sys import argv, exit
+
+import catacomb as C
+
+###--------------------------------------------------------------------------
+### Random utilities.
+
+def words(s):
+ """Split S into 32-bit pieces and report their values as hex."""
+ return ' '.join('%08x' % C.MP.loadb(s[i:i + 4])
+ for i in xrange(0, len(s), 4))
+
+def words_64(s):
+ """Split S into 64-bit pieces and report their values as hex."""
+ return ' '.join('%016x' % C.MP.loadb(s[i:i + 8])
+ for i in xrange(0, len(s), 8))
+
+def repmask(val, wd, n):
+ """Return a mask consisting of N copies of the WD-bit value VAL."""
+ v = C.GF(val)
+ a = C.GF(0)
+ for i in xrange(n): a = (a << wd) | v
+ return a
+
+def combs(things, k):
+ """Iterate over all possible combinations of K of the THINGS."""
+ ii = range(k)
+ n = len(things)
+ while True:
+ yield [things[i] for i in ii]
+ for j in xrange(k):
+ if j == k - 1: lim = n
+ else: lim = ii[j + 1]
+ i = ii[j] + 1
+ if i < lim:
+ ii[j] = i
+ break
+ ii[j] = j
+ else:
+ return
+
+POLYMAP = {}
+
+def poly(nbits):
+ """
+ Return the lexically first irreducible polynomial of degree NBITS of lowest
+ weight.
+ """
+ try: return POLYMAP[nbits]
+ except KeyError: pass
+ base = C.GF(0).setbit(nbits).setbit(0)
+ for k in xrange(1, nbits, 2):
+ for cc in combs(range(1, nbits), k):
+ p = base + sum(C.GF(0).setbit(c) for c in cc)
+ if p.irreduciblep(): POLYMAP[nbits] = p; return p
+ raise ValueError, nbits
+
+def gcm_mangle(x):
+ """Flip the bits within each byte according to GCM's insane convention."""
+ y = C.WriteBuffer()
+ for b in x:
+ b = ord(b)
+ bb = 0
+ for i in xrange(8):
+ bb <<= 1
+ if b&1: bb |= 1
+ b >>= 1
+ y.putu8(bb)
+ return y.contents
+
+def endswap_words_32(x):
+ """End-swap each 32-bit word of X."""
+ x = C.ReadBuffer(x)
+ y = C.WriteBuffer()
+ while x.left: y.putu32l(x.getu32b())
+ return y.contents
+
+def endswap_words_64(x):
+ """End-swap each 64-bit word of X."""
+ x = C.ReadBuffer(x)
+ y = C.WriteBuffer()
+ while x.left: y.putu64l(x.getu64b())
+ return y.contents
+
+def endswap_bytes(x):
+ """End-swap X by bytes."""
+ y = C.WriteBuffer()
+ for ch in reversed(x): y.put(ch)
+ return y.contents
+
+def gfmask(n):
+ return C.GF(C.MP(0).setbit(n) - 1)
+
+def gcm_mul(x, y):
+ """Multiply X and Y according to the GCM rules."""
+ w = len(x)
+ p = poly(8*w)
+ u, v = C.GF.loadl(gcm_mangle(x)), C.GF.loadl(gcm_mangle(y))
+ z = (u*v)%p
+ return gcm_mangle(z.storel(w))
+
+DEMOMAP = {}
+def demo(func):
+ name = func.func_name
+ assert(name.startswith('demo_'))
+ DEMOMAP[name[5:].replace('_', '-')] = func
+ return func
+
+def iota(i = 0):
+ vi = [i]
+ def next(): vi[0] += 1; return vi[0] - 1
+ return next
+
+###--------------------------------------------------------------------------
+### Portable table-driven implementation.
+
+def shift_left(x):
+ """Given a field element X (in external format), return X t."""
+ w = len(x)
+ p = poly(8*w)
+ return gcm_mangle(C.GF.storel((C.GF.loadl(gcm_mangle(x)) << 1)%p))
+
+def table_common(u, v, flip, getword, ixmask):
+ """
+ Multiply U by V using table lookup; common for `table-b' and `table-l'.
+
+ This matches the `simple_mulk_...' implementation in `gcm.c'. One-entry
+ per bit is the best we can manage if we want a constant-time
+ implementation: processing n bits at a time means we need to scan
+ (2^n - 1)/n times as much memory.
+
+ * FLIP is a function (assumed to be an involution) on one argument X to
+ convert X from external format to table-entry format or back again.
+
+ * GETWORD is a function on one argument B to retrieve the next 32-bit
+ chunk of a field element held in a `ReadBuffer'. Bits within a word
+ are processed most-significant first.
+
+ * IXMASK is a mask XORed into table indices to permute the table so that
+ it's order matches that induced by GETWORD.
+
+ The table is built such that tab[i XOR IXMASK] = U t^i.
+ """
+ w = len(u); assert(w == len(v))
+ a = C.ByteString.zero(w)
+ tab = [None]*(8*w)
+ for i in xrange(8*w):
+ print ';; %9s = %7s = %s' % ('utab[%d]' % i, 'u t^%d' % i, words(u))
+ tab[i ^ ixmask] = flip(u)
+ u = shift_left(u)
+ v = C.ReadBuffer(v)
+ i = 0
+ while v.left:
+ t = getword(v)
+ for j in xrange(32):
+ bit = (t >> 31)&1
+ if bit: a ^= tab[i]
+ print ';; %6s = %d: a <- %s [%9s = %s]' % \
+ ('v[%d]' % (i ^ ixmask), bit, words(a),
+ 'utab[%d]' % (i ^ ixmask), words(tab[i]))
+ i += 1; t <<= 1
+ return flip(a)
+
+@demo
+def demo_table_b(u, v):
+ """Big-endian table lookup."""
+ return table_common(u, v, lambda x: x, lambda b: b.getu32b(), 0)
+
+@demo
+def demo_table_l(u, v):
+ """Little-endian table lookup."""
+ return table_common(u, v, endswap_words, lambda b: b.getu32l(), 0x18)
+
+###--------------------------------------------------------------------------
+### Implementation using 64×64->128-bit binary polynomial multiplication.
+
+_i = iota()
+TAG_INPUT_U = _i()
+TAG_INPUT_V = _i()
+TAG_KPIECE_U = _i()
+TAG_KPIECE_V = _i()
+TAG_PRODPIECE = _i()
+TAG_PRODSUM = _i()
+TAG_PRODUCT = _i()
+TAG_SHIFTED = _i()
+TAG_REDCBITS = _i()
+TAG_REDCFULL = _i()
+TAG_REDCMIX = _i()
+TAG_OUTPUT = _i()
+
+def split_gf(x, n):
+ n /= 8
+ return [C.GF.loadb(x[i:i + n]) for i in xrange(0, len(x), n)]
+
+def join_gf(xx, n):
+ x = C.GF(0)
+ for i in xrange(len(xx)): x = (x << n) | xx[i]
+ return x
+
+def present_gf(x, w, n, what):
+ firstp = True
+ m = gfmask(n)
+ for i in xrange(0, w, 128):
+ print ';; %12s%c =%s' % \
+ (firstp and what or '',
+ firstp and ':' or ' ',
+ ''.join([j < w
+ and ' 0x%s' % hex(((x >> j)&m).storeb(n/8))
+ or ''
+ for j in xrange(i, i + 128, n)]))
+ firstp = False
+
+def present_gf_pclmul(tag, wd, x, w, n, what):
+ if tag != TAG_PRODPIECE: present_gf(x, w, n, what)
+
+def reverse(x, w):
+ return C.GF.loadl(x.storeb(w/8))
+
+def rev32(x):
+ w = x.noctets
+ m_ffff = repmask(0xffff, 32, w/4)
+ m_ff = repmask(0xff, 16, w/2)
+ x = ((x&m_ffff) << 16) | ((x >> 16)&m_ffff)
+ x = ((x&m_ff) << 8) | ((x >> 8)&m_ff)
+ return x
+
+def rev8(x):
+ w = x.noctets
+ m_0f = repmask(0x0f, 8, w)
+ m_33 = repmask(0x33, 8, w)
+ m_55 = repmask(0x55, 8, w)
+ x = ((x&m_0f) << 4) | ((x >> 4)&m_0f)
+ x = ((x&m_33) << 2) | ((x >> 2)&m_33)
+ x = ((x&m_55) << 1) | ((x >> 1)&m_55)
+ return x
+
+def present_gf_mullp64(tag, wd, x, w, n, what):
+ if tag == TAG_PRODPIECE or tag == TAG_REDCFULL:
+ return
+ elif (wd == 128 or wd == 64) and TAG_PRODSUM <= tag <= TAG_PRODUCT:
+ y = x
+ elif (wd == 96 or wd == 192 or wd == 256) and \
+ TAG_PRODSUM <= tag < TAG_OUTPUT:
+ y = x
+ else:
+ xx = x.storeb(w/8)
+ extra = len(xx)%8
+ if extra: xx += C.ByteString.zero(8 - extra)
+ yb = C.WriteBuffer()
+ for i in xrange(len(xx), 0, -8): yb.put(xx[i - 8:i])
+ y = C.GF.loadb(yb.contents)
+ present_gf(y, (w + 63)&~63, n, what)
+
+def present_gf_pmull(tag, wd, x, w, n, what):
+ if tag == TAG_PRODPIECE or tag == TAG_REDCFULL or tag == TAG_SHIFTED:
+ return
+ elif tag == TAG_INPUT_V or tag == TAG_KPIECE_V:
+ bx = C.ReadBuffer(x.storeb(w/8))
+ by = C.WriteBuffer()
+ while bx.left: chunk = bx.get(8); by.put(chunk).put(chunk)
+ x = C.GF.loadb(by.contents)
+ w *= 2
+ elif TAG_PRODSUM <= tag <= TAG_PRODUCT:
+ x <<= 1
+ y = reverse(rev8(x), w)
+ present_gf(y, w, n, what)
+
+def poly64_mul_simple(u, v, presfn, wd, dispwd, mulwd, uwhat, vwhat):
+ """
+ Multiply U by V, returning the product.
+
+ This is the fallback long multiplication.
+ """
+
+ uw, vw = 8*len(u), 8*len(v)
+
+ ## We start by carving the operands into 64-bit pieces. This is
+ ## straightforward except for the 96-bit case, where we end up with two
+ ## short pieces which we pad at the beginning.
+ if uw%mulwd: pad = (-uw)%mulwd; u += C.ByteString.zero(pad); uw += pad
+ if vw%mulwd: pad = (-uw)%mulwd; v += C.ByteString.zero(pad); vw += pad
+ uu = split_gf(u, mulwd)
+ vv = split_gf(v, mulwd)
+
+ ## Report and accumulate the individual product pieces.
+ x = C.GF(0)
+ ulim, vlim = uw/mulwd, vw/mulwd
+ for i in xrange(ulim + vlim - 2, -1, -1):
+ t = C.GF(0)
+ for j in xrange(max(0, i - vlim + 1), min(vlim, i + 1)):
+ s = uu[ulim - 1 - i + j]*vv[vlim - 1 - j]
+ presfn(TAG_PRODPIECE, wd, s, 2*mulwd, dispwd,
+ '%s_%d %s_%d' % (uwhat, i - j, vwhat, j))
+ t += s
+ presfn(TAG_PRODSUM, wd, t, 2*mulwd, dispwd,
+ '(%s %s)_%d' % (uwhat, vwhat, ulim + vlim - 2 - i))
+ x += t << (mulwd*i)
+ presfn(TAG_PRODUCT, wd, x, uw + vw, dispwd, '%s %s' % (uwhat, vwhat))
+
+ return x
+
+def poly64_mul_karatsuba(u, v, klimit, presfn, wd,
+ dispwd, mulwd, uwhat, vwhat):
+ """
+ Multiply U by V, returning the product.
+
+ If the length of U and V is at least KLIMIT, and the operands are otherwise
+ suitable, then do Karatsuba--Ofman multiplication; otherwise, delegate to
+ `poly64_mul_simple'.
+ """
+ w = 8*len(u)
+
+ if w < klimit or w != 8*len(v) or w%(2*mulwd) != 0:
+ return poly64_mul_simple(u, v, presfn, wd, dispwd, mulwd, uwhat, vwhat)
+
+ hw = w/2
+ u0, u1 = u[:hw/8], u[hw/8:]
+ v0, v1 = v[:hw/8], v[hw/8:]
+ uu, vv = u0 ^ u1, v0 ^ v1
+
+ presfn(TAG_KPIECE_U, wd, C.GF.loadb(uu), hw, dispwd, '%s*' % uwhat)
+ presfn(TAG_KPIECE_V, wd, C.GF.loadb(vv), hw, dispwd, '%s*' % vwhat)
+ uuvv = poly64_mul_karatsuba(uu, vv, klimit, presfn, wd, dispwd, mulwd,
+ '%s*' % uwhat, '%s*' % vwhat)
+
+ presfn(TAG_KPIECE_U, wd, C.GF.loadb(u0), hw, dispwd, '%s0' % uwhat)
+ presfn(TAG_KPIECE_V, wd, C.GF.loadb(v0), hw, dispwd, '%s0' % vwhat)
+ u0v0 = poly64_mul_karatsuba(u0, v0, klimit, presfn, wd, dispwd, mulwd,
+ '%s0' % uwhat, '%s0' % vwhat)
+
+ presfn(TAG_KPIECE_U, wd, C.GF.loadb(u1), hw, dispwd, '%s1' % uwhat)
+ presfn(TAG_KPIECE_V, wd, C.GF.loadb(v1), hw, dispwd, '%s1' % vwhat)
+ u1v1 = poly64_mul_karatsuba(u1, v1, klimit, presfn, wd, dispwd, mulwd,
+ '%s1' % uwhat, '%s1' % vwhat)
+
+ uvuv = uuvv + u0v0 + u1v1
+ presfn(TAG_PRODSUM, wd, uvuv, w, dispwd, '%s!%s' % (uwhat, vwhat))
+
+ x = u1v1 + (uvuv << hw) + (u0v0 << w)
+ presfn(TAG_PRODUCT, wd, x, 2*w, dispwd, '%s %s' % (uwhat, vwhat))
+ return x
+
+def poly64_common(u, v, presfn, dispwd = 32, mulwd = 64, redcwd = 32,
+ klimit = 256):
+ """
+ Multiply U by V using a primitive 64-bit binary polynomial mutliplier.
+
+ Such a multiplier exists as the appallingly-named `pclmul[lh]q[lh]qdq' on
+ x86, and as `vmull.p64'/`pmull' on ARM.
+
+ Operands arrive in a `register format', which is a byte-swapped variant of
+ the external format. Implementations differ on the precise details,
+ though.
+ """
+
+ ## We work in two main phases: first, calculate the full double-width
+ ## product; and, second, reduce it modulo the field polynomial.
+
+ w = 8*len(u); assert(w == 8*len(v))
+ p = poly(w)
+ presfn(TAG_INPUT_U, w, C.GF.loadb(u), w, dispwd, 'u')
+ presfn(TAG_INPUT_V, w, C.GF.loadb(v), w, dispwd, 'v')
+
+ ## So, on to the first part: the multiplication.
+ x = poly64_mul_karatsuba(u, v, klimit, presfn, w, dispwd, mulwd, 'u', 'v')
+
+ ## Now we have to shift everything up one bit to account for GCM's crazy
+ ## bit ordering.
+ y = x << 1
+ if w == 96: y >>= 64
+ presfn(TAG_SHIFTED, w, y, 2*w, dispwd, 'y')
+
+ ## Now for the reduction.
+ ##
+ ## Our polynomial has the form p = t^d + r where r = SUM_{0<=i<d} r_i t^i,
+ ## with each r_i either 0 or 1. Because we choose the lexically earliest
+ ## irreducible polynomial with the necessary degree, r_i = 1 happens only
+ ## for a small number of tiny i. In our field, we have t^d = r.
+ ##
+ ## We carve the product into convenient n-bit pieces, for some n dividing d
+ ## -- typically n = 32 or 64. Let d = m n, and write y = SUM_{0<=i<2m} y_i
+ ## t^{ni}. The upper portion, the y_i with i >= m, needs reduction; but
+ ## y_i t^{ni} = y_i r t^{n(i-m)}, so we just multiply the top half by r and
+ ## add it to the bottom half. This all depends on r_i = 0 for all i >=
+ ## n/2. We process each nonzero coefficient of r separately, in two
+ ## passes.
+ ##
+ ## Multiplying a chunk y_i by some t^j is the same as shifting it left by j
+ ## bits (or would be if GCM weren't backwards, but let's not worry about
+ ## that right now). The high j bits will spill over into the next chunk,
+ ## while the low n - j bits will stay where they are. It's these high bits
+ ## which cause trouble -- particularly the high bits of the top chunk,
+ ## since we'll add them on to y_m, which will need further reduction. But
+ ## only the topmost j bits will do this.
+ ##
+ ## The trick is that we do all of the bits which spill over first -- all of
+ ## the top j bits in each chunk, for each j -- in one pass, and then a
+ ## second pass of all the bits which don't. Because j, j' < n/2 for any
+ ## two nonzero coefficient degrees j and j', we have j + j' < n whence j <
+ ## n - j' -- so all of the bits contributed to y_m will be handled in the
+ ## second pass when we handle the bits that don't spill over.
+ rr = [i for i in xrange(1, w) if p.testbit(i)]
+ m = gfmask(redcwd)
+
+ ## Handle the spilling bits.
+ yy = split_gf(y.storeb(w/4), redcwd)
+ b = C.GF(0)
+ for rj in rr:
+ br = [(yi << (redcwd - rj))&m for yi in yy[w/redcwd:]]
+ presfn(TAG_REDCBITS, w, join_gf(br, redcwd), w, dispwd, 'b(%d)' % rj)
+ b += join_gf(br, redcwd) << (w - redcwd)
+ presfn(TAG_REDCFULL, w, b, 2*w, dispwd, 'b')
+ s = y + b
+ presfn(TAG_REDCMIX, w, s, 2*w, dispwd, 's')
+
+ ## Handle the nonspilling bits.
+ ss = split_gf(s.storeb(w/4), redcwd)
+ a = C.GF(0)
+ for rj in rr:
+ ar = [si >> rj for si in ss[w/redcwd:]]
+ presfn(TAG_REDCBITS, w, join_gf(ar, redcwd), w, dispwd, 'a(%d)' % rj)
+ a += join_gf(ar, redcwd)
+ presfn(TAG_REDCFULL, w, a, w, dispwd, 'a')
+
+ ## Mix everything together.
+ m = gfmask(w)
+ z = (s&m) + (s >> w) + a
+ presfn(TAG_OUTPUT, w, z, w, dispwd, 'z')
+
+ ## And we're done.
+ return z.storeb(w/8)
+
+@demo
+def demo_pclmul(u, v):
+ return poly64_common(u, v, presfn = present_gf_pclmul)
+
+@demo
+def demo_vmullp64(u, v):
+ w = 8*len(u)
+ return poly64_common(u, v, presfn = present_gf_mullp64,
+ redcwd = w%64 == 32 and 32 or 64)
+
+@demo
+def demo_pmull(u, v):
+ w = 8*len(u)
+ return poly64_common(u, v, presfn = present_gf_pmull,
+ redcwd = w%64 == 32 and 32 or 64)
+
+###--------------------------------------------------------------------------
+### @@@ Random debris to be deleted. @@@
+
+def cutting_room_floor():
+
+ x = C.bytes('cde4bef260d7bcda163547d348b7551195e77022907dd1df')
+ y = C.bytes('f7dac5c9941d26d0c6eb14ad568f86edd1dc9268eeee5332')
+
+ u, v = C.GF.loadb(x), C.GF.loadb(y)
+
+ g = u*v << 1
+ print 'y = %s' % words(g.storeb(48))
+ b1 = (g&repmask(0x01, 32, 6)) << 191
+ b2 = (g&repmask(0x03, 32, 6)) << 190
+ b7 = (g&repmask(0x7f, 32, 6)) << 185
+ b = b1 + b2 + b7
+ print 'b = %s' % words(b.storeb(48)[0:28])
+ h = g + b
+ print 'w = %s' % words(h.storeb(48))
+
+ a0 = (h&repmask(0xffffffff, 32, 6)) << 192
+ a1 = (h&repmask(0xfffffffe, 32, 6)) << 191
+ a2 = (h&repmask(0xfffffffc, 32, 6)) << 190
+ a7 = (h&repmask(0xffffff80, 32, 6)) << 185
+ a = a0 + a1 + a2 + a7
+
+ print ' a_1 = %s' % words(a1.storeb(48)[0:24])
+ print ' a_2 = %s' % words(a2.storeb(48)[0:24])
+ print ' a_7 = %s' % words(a7.storeb(48)[0:24])
+
+ print 'low+unit = %s' % words((h + a0).storeb(48)[0:24])
+ print ' low+0,2 = %s' % words((h + a0 + a2).storeb(48)[0:24])
+ print ' 1,7 = %s' % words((a1 + a7).storeb(48)[0:24])
+
+ print 'a = %s' % words(a.storeb(48)[0:24])
+ z = h + a
+ print 'z = %s' % words(z.storeb(48))
+
+ z = gcm_mul(x, y)
+ print 'u v mod p = %s' % words(z)
+
+###--------------------------------------------------------------------------
+### Main program.
+
+style = argv[1]
+u = C.bytes(argv[2])
+v = C.bytes(argv[3])
+zz = DEMOMAP[style](u, v)
+assert zz == gcm_mul(u, v)
+
+###----- That's all, folks --------------------------------------------------